blob: af53c54122523c68698a5d68dc3c04eae8a39ca6 [file] [log] [blame]
/*
* Copyright (C) 2011 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
*************************************************************************
* @file VideoEditorMp3Reader.cpp
* @brief StageFright shell MP3 Reader
*************************************************************************
*/
#define LOG_NDEBUG 1
#define LOG_TAG "VIDEOEDITOR_MP3READER"
/**
* HEADERS
*
*/
#include "M4OSA_Debug.h"
#include "M4SYS_AccessUnit.h"
#include "VideoEditorMp3Reader.h"
#include "VideoEditorUtils.h"
#include "utils/Log.h"
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/MediaBufferGroup.h>
#include <media/stagefright/DataSource.h>
#include <media/stagefright/FileSource.h>
#include <media/stagefright/MediaBuffer.h>
#include <media/stagefright/MediaDefs.h>
#include <media/stagefright/MediaExtractor.h>
#include <media/stagefright/MediaSource.h>
#include <media/stagefright/MetaData.h>
/**
* SOURCE CLASS
*/
namespace android {
/**
* ENGINE INTERFACE
*/
/**
**************************************************************************
* structure VideoEditorMp3Reader_Context
* @brief This structure defines the context of the SF MP3 reader shell.
**************************************************************************
*/
typedef struct {
sp<DataSource> mDataSource;
sp<MediaExtractor> mExtractor;
sp<MediaSource> mMediaSource;
M4_AudioStreamHandler* mAudioStreamHandler;
M4SYS_AccessUnit mAudioAu;
M4OSA_Time mMaxDuration;
M4OSA_UInt8 mStreamNumber;
M4OSA_Bool mSeeking;
M4OSA_Time mSeekTime;
uint32_t mExtractorFlags;
} VideoEditorMp3Reader_Context;
/**
****************************************************************************
* @brief create an instance of the MP3 reader
* @note allocates the context
*
* @param pContext: (OUT) pointer on a reader context
*
* @return M4NO_ERROR there is no error
* @return M4ERR_ALLOC a memory allocation has failed
* @return M4ERR_PARAMETER at least one parameter is not valid
****************************************************************************
*/
M4OSA_ERR VideoEditorMp3Reader_create(M4OSA_Context *pContext) {
M4OSA_ERR err = M4NO_ERROR;
VideoEditorMp3Reader_Context *pReaderContext = M4OSA_NULL;
VIDEOEDITOR_CHECK(M4OSA_NULL != pContext, M4ERR_PARAMETER);
ALOGV("VideoEditorMp3Reader_create begin");
/* Context allocation & initialization */
SAFE_MALLOC(pReaderContext, VideoEditorMp3Reader_Context, 1,
"VideoEditorMp3Reader");
pReaderContext->mAudioStreamHandler = M4OSA_NULL;
pReaderContext->mAudioAu.dataAddress = M4OSA_NULL;
pReaderContext->mMaxDuration = 0;
*pContext = pReaderContext;
cleanUp:
if (M4NO_ERROR == err) {
ALOGV("VideoEditorMp3Reader_create no error");
} else {
ALOGV("VideoEditorMp3Reader_create ERROR 0x%X", err);
}
ALOGV("VideoEditorMp3Reader_create end");
return err;
}
/**
*******************************************************************************
* @brief destroy the instance of the MP3 reader
* @note after this call the context is invalid
* @param context: (IN) Context of the reader
* @return M4NO_ERROR there is no error
* @return M4ERR_PARAMETER The input parameter is not properly set
*******************************************************************************
*/
M4OSA_ERR VideoEditorMp3Reader_destroy(M4OSA_Context pContext) {
M4OSA_ERR err = M4NO_ERROR;
VideoEditorMp3Reader_Context *pReaderContext =
(VideoEditorMp3Reader_Context*)pContext;
VIDEOEDITOR_CHECK(M4OSA_NULL != pReaderContext, M4ERR_PARAMETER);
ALOGV("VideoEditorMp3Reader_destroy begin");
SAFE_FREE(pReaderContext);
cleanUp:
if (M4NO_ERROR == err) {
ALOGV("VideoEditorMp3Reader_destroy no error");
} else {
ALOGV("VideoEditorMp3Reader_destroy ERROR 0x%X", err);
}
ALOGV("VideoEditorMp3Reader_destroy end");
return err;
}
/**
******************************************************************************
* @brief open the reader and initializes its created instance
* @note this function opens the MP3 file
* @param context: (IN) Context of the reader
* @param pFileDescriptor: (IN) Pointer to proprietary data identifying
* the media to open
* @return M4NO_ERROR there is no error
* @return M4ERR_PARAMETER the context is NULL
* @return M4ERR_BAD_CONTEXT provided context is not a valid one
* @return M4ERR_UNSUPPORTED_MEDIA_TYPE the media is DRM protected
******************************************************************************
*/
M4OSA_ERR VideoEditorMp3Reader_open(M4OSA_Context context,
M4OSA_Void* pFileDescriptor){
VideoEditorMp3Reader_Context *pReaderContext =
(VideoEditorMp3Reader_Context*)context;
M4OSA_ERR err = M4NO_ERROR;
ALOGV("VideoEditorMp3Reader_open begin");
/* Check function parameters*/
M4OSA_DEBUG_IF1((M4OSA_NULL == pReaderContext), M4ERR_PARAMETER,
"VideoEditorMp3Reader_open: invalid context pointer");
M4OSA_DEBUG_IF1((M4OSA_NULL == pFileDescriptor), M4ERR_PARAMETER,
"VideoEditorMp3Reader_open: invalid pointer pFileDescriptor");
ALOGV("VideoEditorMp3Reader_open Datasource start %s",
(char*)pFileDescriptor);
pReaderContext->mDataSource = new FileSource ((char*)pFileDescriptor);
ALOGV("VideoEditorMp3Reader_open Datasource end");
if (pReaderContext->mDataSource == NULL) {
ALOGV("VideoEditorMp3Reader_open Datasource error");
return UNKNOWN_ERROR;
}
ALOGV("VideoEditorMp3Reader_open extractor start");
pReaderContext->mExtractor = MediaExtractor::Create(
pReaderContext->mDataSource,MEDIA_MIMETYPE_AUDIO_MPEG);
ALOGV("VideoEditorMp3Reader_open extractor end");
if (pReaderContext->mExtractor == NULL) {
ALOGV("VideoEditorMp3Reader_open extractor error");
return UNKNOWN_ERROR;
}
pReaderContext->mStreamNumber = 0;
int32_t isDRMProtected = 0;
sp<MetaData> meta = pReaderContext->mExtractor->getMetaData();
meta->findInt32(kKeyIsDRM, &isDRMProtected);
if (isDRMProtected) {
ALOGV("VideoEditorMp3Reader_open error - DRM Protected");
return M4ERR_UNSUPPORTED_MEDIA_TYPE;
}
ALOGV("VideoEditorMp3Reader_open end");
return err;
}
/**
**************************************************************************
* @brief close the reader
* @note this function closes the MP3 reader
* @param context: (IN) Context of the reader
* @return M4NO_ERROR there is no error
* @return M4ERR_PARAMETER the context is NULL
**************************************************************************
*/
M4OSA_ERR VideoEditorMp3Reader_close(M4OSA_Context context) {
VideoEditorMp3Reader_Context *pReaderContext =
(VideoEditorMp3Reader_Context*)context;
M4OSA_ERR err = M4NO_ERROR;
ALOGV("VideoEditorMp3Reader_close begin");
/* Check function parameters */
M4OSA_DEBUG_IF1((M4OSA_NULL == pReaderContext), M4ERR_PARAMETER,
"VideoEditorMp3Reader_close: invalid context pointer");
if (pReaderContext->mAudioStreamHandler != NULL) {
if (M4OSA_NULL != pReaderContext->mAudioStreamHandler->\
m_basicProperties.m_pDecoderSpecificInfo) {
free(pReaderContext->mAudioStreamHandler->\
m_basicProperties.m_pDecoderSpecificInfo);
pReaderContext->mAudioStreamHandler->m_basicProperties.\
m_decoderSpecificInfoSize = 0;
pReaderContext->mAudioStreamHandler->m_basicProperties.\
m_pDecoderSpecificInfo = M4OSA_NULL;
}
/* Finally destroy the stream handler */
free(pReaderContext->mAudioStreamHandler);
pReaderContext->mAudioStreamHandler = M4OSA_NULL;
if (pReaderContext->mAudioAu.dataAddress != NULL) {
free(pReaderContext->mAudioAu.dataAddress);
pReaderContext->mAudioAu.dataAddress = NULL;
}
}
pReaderContext->mMediaSource->stop();
pReaderContext->mMediaSource.clear();
pReaderContext->mExtractor.clear();
pReaderContext->mDataSource.clear();
ALOGV("VideoEditorMp3Reader_close end ");
return err;
}
/**
******************************************************************************
* @brief get an option value from the reader
* @note
* it allows the caller to retrieve a property value:
*
* @param context: (IN) Context of the reader
* @param optionId: (IN) indicates the option to get
* @param pValue: (OUT) pointer to structure or value (allocated
* by user) where option is stored
*
* @return M4NO_ERROR there is no error
* @return M4ERR_PARAMETER at least one parameter is not properly set
* @return M4ERR_BAD_OPTION_ID when the option ID is not a valid one
******************************************************************************
*/
M4OSA_ERR VideoEditorMp3Reader_getOption(M4OSA_Context context,
M4OSA_OptionID optionId, M4OSA_DataOption pValue) {
VideoEditorMp3Reader_Context *pReaderContext =
(VideoEditorMp3Reader_Context*)context;
M4OSA_ERR err = M4NO_ERROR;
ALOGV("VideoEditorMp3Reader_getOption begin: optionId= %d ",(int)optionId);
M4OSA_DEBUG_IF1((M4OSA_NULL == pReaderContext), M4ERR_PARAMETER,
"invalid value pointer");
M4OSA_DEBUG_IF1((M4OSA_NULL == pValue), M4ERR_PARAMETER,
"invalid value pointer");
switch(optionId) {
case M4READER_kOptionID_Duration:
{
ALOGV("Mp3Reader duration=%ld",pReaderContext->mMaxDuration);
*(M4OSA_Time*)pValue = pReaderContext->mMaxDuration;
}
break;
case M4READER_kOptionID_Bitrate:
{
M4OSA_UInt32* pBitrate = (M4OSA_UInt32*)pValue;
if (M4OSA_NULL != pReaderContext->mAudioStreamHandler) {
*pBitrate = pReaderContext->mAudioStreamHandler->\
m_basicProperties.m_averageBitRate;
} else {
pBitrate = 0;
err = M4ERR_PARAMETER;
}
}
break;
case M4READER_kOptionID_Mp3Id3v1Tag:
break;
case M4READER_kOptionID_Mp3Id3v2Tag:
break;
case M4READER_kOptionID_GetMetadata:
break;
default :
{
ALOGV("VideoEditorMp3Reader_getOption: M4ERR_BAD_OPTION_ID");
err = M4ERR_BAD_OPTION_ID;
}
}
ALOGV("VideoEditorMp3Reader_getOption end ");
return err;
}
/**
******************************************************************************
* @brief set an option value of the reader
* @note
* it allows the caller to set a property value:
*
* @param context: (IN) Context of the reader
* @param optionId: (IN) Identifier indicating the option to set
* @param pValue: (IN) Pointer to structure or value (allocated
* by user) where option is stored
*
* @return M4NO_ERROR There is no error
* @return M4ERR_BAD_OPTION_ID The option ID is not a valid one
* @return M4ERR_STATE State automaton is not applied
* @return M4ERR_PARAMETER The option parameter is invalid
******************************************************************************
*/
M4OSA_ERR VideoEditorMp3Reader_setOption(M4OSA_Context context,
M4OSA_OptionID optionId, M4OSA_DataOption pValue) {
VideoEditorMp3Reader_Context *pReaderContext =
(VideoEditorMp3Reader_Context*)context;
M4OSA_ERR err = M4NO_ERROR;
ALOGV("VideoEditorMp3Reader_Context begin: optionId: %d Value: %d ",
(int)optionId,(int)pValue);
M4OSA_DEBUG_IF1((M4OSA_NULL == pReaderContext), M4ERR_PARAMETER,
"invalid context pointer");
M4OSA_DEBUG_IF1((M4OSA_NULL == pValue), M4ERR_PARAMETER,
"invalid value pointer");
switch(optionId) {
case M4READER_kOptionID_SetOsaFileReaderFctsPtr:
default :
{
err = M4NO_ERROR;
}
}
ALOGV("VideoEditorMp3Reader_Context end ");
return err;
}
/**
******************************************************************************
* @brief jump into the stream at the specified time
* @note
* @param context: (IN) Context of the reader
* @param pStreamHandler(IN) stream description of the stream to make jump
* @param pTime (I/O)IN:the time to jump to (in ms)
* OUT: the time to which the stream really jumped
* @return M4NO_ERROR there is no error
* @return M4ERR_PARAMETER at least one parameter is not properly set
******************************************************************************
*/
M4OSA_ERR VideoEditorMp3Reader_jump(M4OSA_Context context,
M4_StreamHandler *pStreamHandler, M4OSA_Int32* pTime) {
VideoEditorMp3Reader_Context *pReaderContext =
(VideoEditorMp3Reader_Context*)context;
M4SYS_StreamID streamIdArray[2];
M4OSA_ERR err = M4NO_ERROR;
M4SYS_AccessUnit* pAu;
M4OSA_Time time64 = (M4OSA_Time)*pTime;
ALOGV("VideoEditorMp3Reader_jump begin");
M4OSA_DEBUG_IF1((pReaderContext == 0), M4ERR_PARAMETER,
"VideoEditorMp3Reader_jump: invalid context");
M4OSA_DEBUG_IF1((pStreamHandler == 0), M4ERR_PARAMETER,
"VideoEditorMp3Reader_jump: invalid pointer to M4_StreamHandler");
M4OSA_DEBUG_IF1((pTime == 0), M4ERR_PARAMETER,
"VideoEditorMp3Reader_jump: invalid time pointer");
if(pStreamHandler == (M4_StreamHandler*)pReaderContext->\
mAudioStreamHandler){
pAu = &pReaderContext->mAudioAu;
} else {
ALOGV("VideoEditorMp3Reader_jump: passed StreamHandler is not known");
return M4ERR_PARAMETER;
}
streamIdArray[0] = pStreamHandler->m_streamId;
streamIdArray[1] = 0;
ALOGV("VideoEditorMp3Reader_jump time ms %ld ", time64);
pAu->CTS = time64;
pAu->DTS = time64;
time64 = time64 * 1000; /* Convert the time into micro sec */
ALOGV("VideoEditorMp3Reader_jump time us %ld ", time64);
pReaderContext->mSeeking = M4OSA_TRUE;
pReaderContext->mSeekTime = time64;
time64 = time64 / 1000; /* Convert the time into milli sec */
*pTime = (M4OSA_Int32)time64;
ALOGV("VideoEditorMp3Reader_jump end ");
return err;
}
/**
*******************************************************************************
* @brief Get the next stream found in the media file
*
* @param context: (IN) Context of the reader
* @param pMediaFamily: (OUT) pointer to a user allocated
* M4READER_MediaFamily that will be filled with
* the media family of the found stream
* @param pStreamHandler: (OUT) pointer to a stream handler that will be
* allocated and filled with stream description
*
* @return M4NO_ERROR there is no error
* @return M4WAR_NO_MORE_STREAM no more available stream in the media
* @return M4ERR_PARAMETER at least one parameter is not properly set
*******************************************************************************
*/
M4OSA_ERR VideoEditorMp3Reader_getNextStream(M4OSA_Context context,
M4READER_MediaFamily *pMediaFamily,
M4_StreamHandler **pStreamHandlerParam) {
VideoEditorMp3Reader_Context *pReaderContext =
(VideoEditorMp3Reader_Context*)context;
M4OSA_ERR err = M4NO_ERROR;
M4SYS_StreamID streamIdArray[2];
M4SYS_StreamDescription streamDesc;
M4_AudioStreamHandler* pAudioStreamHandler;
M4_StreamHandler* pStreamHandler;
M4OSA_UInt8 type, temp;
M4OSA_Bool haveAudio = M4OSA_FALSE;
sp<MetaData> meta = NULL;
int64_t Duration;
ALOGV("VideoEditorMp3Reader_getNextStream begin");
M4OSA_DEBUG_IF1((pReaderContext == 0), M4ERR_PARAMETER,
"VideoEditorMp3Reader_getNextStream: invalid context");
M4OSA_DEBUG_IF1((pMediaFamily == 0), M4ERR_PARAMETER,
"VideoEditorMp3Reader_getNextStream: invalid pointer to MediaFamily");
M4OSA_DEBUG_IF1((pStreamHandlerParam == 0), M4ERR_PARAMETER,
"VideoEditorMp3Reader_getNextStream: invalid pointer to StreamHandler");
ALOGV("VideoEditorMp3Reader_getNextStream stream number = %d",
pReaderContext->mStreamNumber);
if (pReaderContext->mStreamNumber >= 1) {
ALOGV("VideoEditorMp3Reader_getNextStream max number of stream reached");
return M4WAR_NO_MORE_STREAM;
}
pReaderContext->mStreamNumber = pReaderContext->mStreamNumber + 1;
ALOGV("VideoEditorMp3Reader_getNextStream number of Tracks%d",
pReaderContext->mExtractor->countTracks());
for (temp = 0; temp < pReaderContext->mExtractor->countTracks(); temp++) {
meta = pReaderContext->mExtractor->getTrackMetaData(temp);
const char *mime;
CHECK(meta->findCString(kKeyMIMEType, &mime));
if (!haveAudio && !strncasecmp(mime, "audio/", 6)) {
pReaderContext->mMediaSource =
pReaderContext->mExtractor->getTrack(temp);
pReaderContext->mMediaSource->start();
haveAudio = true;
}
if (haveAudio) {
break;
}
}
if (!haveAudio) {
ALOGV("VideoEditorMp3Reader_getNextStream no more stream ");
pReaderContext->mDataSource.clear();
return M4WAR_NO_MORE_STREAM;
}
pReaderContext->mExtractorFlags = pReaderContext->mExtractor->flags();
*pMediaFamily = M4READER_kMediaFamilyAudio;
streamDesc.duration = meta->findInt64(kKeyDuration, &Duration);
streamDesc.duration = (M4OSA_Time)Duration/1000;
meta->findInt32(kKeyBitRate, (int32_t*)&streamDesc.averageBitrate);
meta->findInt32(kKeySampleRate, (int32_t*)&streamDesc.timeScale);
ALOGV("Bitrate = %d, SampleRate = %d duration = %lld",
streamDesc.averageBitrate,streamDesc.timeScale,Duration/1000);
streamDesc.streamType = M4SYS_kMP3;
streamDesc.profileLevel = 0xFF ;
streamDesc.streamID = pReaderContext->mStreamNumber;
streamDesc.decoderSpecificInfo = M4OSA_NULL;
streamDesc.decoderSpecificInfoSize = 0;
streamDesc.maxBitrate = streamDesc.averageBitrate;
/* Allocate the audio stream handler and set its parameters */
pAudioStreamHandler = (M4_AudioStreamHandler*)M4OSA_32bitAlignedMalloc(
sizeof(M4_AudioStreamHandler), M4READER_MP3,
(M4OSA_Char*)"M4_AudioStreamHandler");
if (pAudioStreamHandler == M4OSA_NULL) {
ALOGV("VideoEditorMp3Reader_getNextStream malloc failed");
pReaderContext->mMediaSource->stop();
pReaderContext->mMediaSource.clear();
pReaderContext->mDataSource.clear();
return M4ERR_ALLOC;
}
pStreamHandler =(M4_StreamHandler*)(pAudioStreamHandler);
*pStreamHandlerParam = pStreamHandler;
pReaderContext->mAudioStreamHandler = pAudioStreamHandler;
pAudioStreamHandler->m_structSize = sizeof(M4_AudioStreamHandler);
if (meta == NULL) {
ALOGV("VideoEditorMp3Reader_getNextStream meta is NULL");
}
pAudioStreamHandler->m_samplingFrequency = streamDesc.timeScale;
pStreamHandler->m_pDecoderSpecificInfo =
(M4OSA_UInt8*)(streamDesc.decoderSpecificInfo);
pStreamHandler->m_decoderSpecificInfoSize =
streamDesc.decoderSpecificInfoSize;
meta->findInt32(kKeyChannelCount,
(int32_t*)&pAudioStreamHandler->m_nbChannels);
pAudioStreamHandler->m_byteFrameLength = 1152;
pAudioStreamHandler->m_byteSampleSize = 2;
pStreamHandler->m_pUserData = NULL;
pStreamHandler->m_streamId = streamDesc.streamID;
pStreamHandler->m_duration = streamDesc.duration;
pReaderContext->mMaxDuration = streamDesc.duration;
pStreamHandler->m_averageBitRate = streamDesc.averageBitrate;
pStreamHandler->m_maxAUSize = 0;
pStreamHandler->m_streamType = M4DA_StreamTypeAudioMp3;
ALOGV("VideoEditorMp3Reader_getNextStream end ");
return err;
}
/**
*******************************************************************************
* @brief fill the access unit structure with initialization values
* @param context: (IN) Context of the reader
* @param pStreamHandler: (IN) pointer to the stream handler to which
* the access unit will be associated
* @param pAccessUnit: (IN/OUT) pointer to the access unit (allocated by
* the caller) to initialize
* @return M4NO_ERROR there is no error
* @return M4ERR_PARAMETER at least one parameter is not properly set
*******************************************************************************
*/
M4OSA_ERR VideoEditorMp3Reader_fillAuStruct(M4OSA_Context context,
M4_StreamHandler *pStreamHandler, M4_AccessUnit *pAccessUnit) {
VideoEditorMp3Reader_Context *pReaderContext =
(VideoEditorMp3Reader_Context*)context;
M4SYS_AccessUnit *pAu;
M4OSA_DEBUG_IF1((pReaderContext == 0), M4ERR_PARAMETER,
"VideoEditorMp3Reader_fillAuStruct: invalid context");
M4OSA_DEBUG_IF1((pStreamHandler == 0), M4ERR_PARAMETER,
"VideoEditorMp3Reader_fillAuStruct invalid pointer to StreamHandler");
M4OSA_DEBUG_IF1((pAccessUnit == 0), M4ERR_PARAMETER,
"VideoEditorMp3Reader_fillAuStruct: invalid pointer to M4_AccessUnit");
ALOGV("VideoEditorMp3Reader_fillAuStruct start ");
if(pStreamHandler == (M4_StreamHandler*)pReaderContext->\
mAudioStreamHandler){
pAu = &pReaderContext->mAudioAu;
} else {
ALOGV("VideoEditorMp3Reader_fillAuStruct StreamHandler is not known");
return M4ERR_PARAMETER;
}
/* Initialize pAu structure */
pAu->dataAddress = M4OSA_NULL;
pAu->size = 0;
pAu->CTS = 0;
pAu->DTS = 0;
pAu->attribute = 0;
pAu->nbFrag = 0;
/* Initialize pAccessUnit structure */
pAccessUnit->m_size = 0;
pAccessUnit->m_CTS = 0;
pAccessUnit->m_DTS = 0;
pAccessUnit->m_attribute = 0;
pAccessUnit->m_dataAddress = M4OSA_NULL;
pAccessUnit->m_maxsize = pStreamHandler->m_maxAUSize;
pAccessUnit->m_streamID = pStreamHandler->m_streamId;
pAccessUnit->m_structSize = sizeof(M4_AccessUnit);
ALOGV("VideoEditorMp3Reader_fillAuStruct end");
return M4NO_ERROR;
}
/**
*******************************************************************************
* @brief reset the stream, i.e seek it to the beginning
* @note
* @param context: (IN) Context of the reader
* @param pStreamHandler (IN) The stream handler of the stream to reset
* @return M4NO_ERROR there is no error
* @return M4ERR_PARAMETER at least one parameter is not properly set
*******************************************************************************
*/
M4OSA_ERR VideoEditorMp3Reader_reset(M4OSA_Context context,
M4_StreamHandler *pStreamHandler) {
VideoEditorMp3Reader_Context *pReaderContext =
(VideoEditorMp3Reader_Context*)context;
M4OSA_ERR err = M4NO_ERROR;
M4SYS_StreamID streamIdArray[2];
M4SYS_AccessUnit* pAu;
M4OSA_Time time64 = 0;
ALOGV("VideoEditorMp3Reader_reset start");
M4OSA_DEBUG_IF1((pReaderContext == 0), M4ERR_PARAMETER,
"VideoEditorMp3Reader_reset: invalid context");
M4OSA_DEBUG_IF1((pStreamHandler == 0), M4ERR_PARAMETER,
"VideoEditorMp3Reader_reset: invalid pointer to M4_StreamHandler");
if (pStreamHandler == (M4_StreamHandler*)pReaderContext->\
mAudioStreamHandler) {
pAu = &pReaderContext->mAudioAu;
} else {
ALOGV("VideoEditorMp3Reader_reset StreamHandler is not known");
return M4ERR_PARAMETER;
}
streamIdArray[0] = pStreamHandler->m_streamId;
streamIdArray[1] = 0;
pAu->CTS = time64;
pAu->DTS = time64;
pReaderContext->mSeeking = M4OSA_TRUE;
pReaderContext->mSeekTime = time64;
ALOGV("VideoEditorMp3Reader_reset end");
return err;
}
/**
*******************************************************************************
* @brief Gets an access unit (AU) from the stream handler source.
* @note AU is the smallest possible amount of data to be decoded by decoder
*
* @param context: (IN) Context of the reader
* @param pStreamHandler (IN) The stream handler of the stream to make jump
* @param pAccessUnit (I/O)Pointer to an access unit to fill with read data
* @return M4NO_ERROR there is no error
* @return M4ERR_PARAMETER at least one parameter is not properly set
* @returns M4ERR_ALLOC memory allocation failed
* @returns M4WAR_NO_MORE_AU there are no more access unit in the stream
*******************************************************************************
*/
M4OSA_ERR VideoEditorMp3Reader_getNextAu(M4OSA_Context context,
M4_StreamHandler *pStreamHandler, M4_AccessUnit *pAccessUnit) {
VideoEditorMp3Reader_Context *pReaderContext =
(VideoEditorMp3Reader_Context*)context;
M4OSA_ERR err = M4NO_ERROR;
M4SYS_AccessUnit* pAu;
MediaBuffer *mAudioBuffer;
MediaSource::ReadOptions options;
ALOGV("VideoEditorMp3Reader_getNextAu start");
M4OSA_DEBUG_IF1((pReaderContext == 0), M4ERR_PARAMETER,
"VideoEditorMp3Reader_getNextAu: invalid context");
M4OSA_DEBUG_IF1((pStreamHandler == 0), M4ERR_PARAMETER,
"VideoEditorMp3Reader_getNextAu: invalid pointer to M4_StreamHandler");
M4OSA_DEBUG_IF1((pAccessUnit == 0), M4ERR_PARAMETER,
"VideoEditorMp3Reader_getNextAu: invalid pointer to M4_AccessUnit");
if (pStreamHandler == (M4_StreamHandler*)pReaderContext->\
mAudioStreamHandler) {
pAu = &pReaderContext->mAudioAu;
} else {
ALOGV("VideoEditorMp3Reader_getNextAu: StreamHandler is not known\n");
return M4ERR_PARAMETER;
}
if (pReaderContext->mSeeking) {
options.setSeekTo(pReaderContext->mSeekTime);
}
pReaderContext->mMediaSource->read(&mAudioBuffer, &options);
if (mAudioBuffer != NULL) {
if ((pAu->dataAddress == NULL) ||
(pAu->size < mAudioBuffer->range_length())) {
if (pAu->dataAddress != NULL) {
free((M4OSA_Int32*)pAu->dataAddress);
pAu->dataAddress = NULL;
}
pAu->dataAddress = (M4OSA_Int32*)M4OSA_32bitAlignedMalloc(
(mAudioBuffer->range_length() + 3) & ~0x3,
M4READER_MP3, (M4OSA_Char*)"pAccessUnit->m_dataAddress" );
if (pAu->dataAddress == NULL) {
ALOGV("VideoEditorMp3Reader_getNextAu malloc failed");
pReaderContext->mMediaSource->stop();
pReaderContext->mMediaSource.clear();
pReaderContext->mDataSource.clear();
return M4ERR_ALLOC;
}
}
pAu->size = mAudioBuffer->range_length();
memcpy((M4OSA_MemAddr8)pAu->dataAddress,
(const char *)mAudioBuffer->data() + mAudioBuffer->range_offset(),
mAudioBuffer->range_length());
mAudioBuffer->meta_data()->findInt64(kKeyTime, (int64_t*)&pAu->CTS);
pAu->CTS = pAu->CTS / 1000; /*converting the microsec to millisec */
pAu->DTS = pAu->CTS;
pAu->attribute = M4SYS_kFragAttrOk;
mAudioBuffer->release();
ALOGV("VideoEditorMp3Reader_getNextAu AU CTS = %ld",pAu->CTS);
pAccessUnit->m_dataAddress = (M4OSA_Int8*) pAu->dataAddress;
pAccessUnit->m_size = pAu->size;
pAccessUnit->m_CTS = pAu->CTS;
pAccessUnit->m_DTS = pAu->DTS;
pAccessUnit->m_attribute = pAu->attribute;
} else {
ALOGV("VideoEditorMp3Reader_getNextAu EOS reached.");
pAccessUnit->m_size=0;
err = M4WAR_NO_MORE_AU;
}
pAu->nbFrag = 0;
options.clearSeekTo();
pReaderContext->mSeeking = M4OSA_FALSE;
mAudioBuffer = NULL;
ALOGV("VideoEditorMp3Reader_getNextAu end");
return err;
}
extern "C" {
M4OSA_ERR VideoEditorMp3Reader_getInterface(
M4READER_MediaType *pMediaType,
M4READER_GlobalInterface **pRdrGlobalInterface,
M4READER_DataInterface **pRdrDataInterface) {
M4OSA_ERR err = M4NO_ERROR;
ALOGV("VideoEditorMp3Reader_getInterface: begin");
/* Input parameters check */
VIDEOEDITOR_CHECK(M4OSA_NULL != pMediaType, M4ERR_PARAMETER);
VIDEOEDITOR_CHECK(M4OSA_NULL != pRdrGlobalInterface, M4ERR_PARAMETER);
VIDEOEDITOR_CHECK(M4OSA_NULL != pRdrDataInterface, M4ERR_PARAMETER);
SAFE_MALLOC(*pRdrGlobalInterface, M4READER_GlobalInterface, 1,
"VideoEditorMp3Reader_getInterface");
SAFE_MALLOC(*pRdrDataInterface, M4READER_DataInterface, 1,
"VideoEditorMp3Reader_getInterface");
*pMediaType = M4READER_kMediaTypeMP3;
(*pRdrGlobalInterface)->m_pFctCreate = VideoEditorMp3Reader_create;
(*pRdrGlobalInterface)->m_pFctDestroy = VideoEditorMp3Reader_destroy;
(*pRdrGlobalInterface)->m_pFctOpen = VideoEditorMp3Reader_open;
(*pRdrGlobalInterface)->m_pFctClose = VideoEditorMp3Reader_close;
(*pRdrGlobalInterface)->m_pFctGetOption = VideoEditorMp3Reader_getOption;
(*pRdrGlobalInterface)->m_pFctSetOption = VideoEditorMp3Reader_setOption;
(*pRdrGlobalInterface)->m_pFctGetNextStream =
VideoEditorMp3Reader_getNextStream;
(*pRdrGlobalInterface)->m_pFctFillAuStruct =
VideoEditorMp3Reader_fillAuStruct;
(*pRdrGlobalInterface)->m_pFctStart = M4OSA_NULL;
(*pRdrGlobalInterface)->m_pFctStop = M4OSA_NULL;
(*pRdrGlobalInterface)->m_pFctJump = VideoEditorMp3Reader_jump;
(*pRdrGlobalInterface)->m_pFctReset = VideoEditorMp3Reader_reset;
(*pRdrGlobalInterface)->m_pFctGetPrevRapTime = M4OSA_NULL;
(*pRdrDataInterface)->m_pFctGetNextAu = VideoEditorMp3Reader_getNextAu;
(*pRdrDataInterface)->m_readerContext = M4OSA_NULL;
cleanUp:
if( M4NO_ERROR == err )
{
ALOGV("VideoEditorMp3Reader_getInterface no error");
}
else
{
SAFE_FREE(*pRdrGlobalInterface);
SAFE_FREE(*pRdrDataInterface);
ALOGV("VideoEditorMp3Reader_getInterface ERROR 0x%X", err);
}
ALOGV("VideoEditorMp3Reader_getInterface: end");
return err;
}
} /* extern "C" */
} /* namespace android */