Home | History | Annotate | Download | only in src
      1 /*
      2  * Copyright (C) 2011 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 /**
     17 *************************************************************************
     18 * @file   VideoEditorMp3Reader.cpp
     19 * @brief  StageFright shell MP3 Reader
     20 *************************************************************************
     21 */
     22 #define LOG_NDEBUG 1
     23 #define LOG_TAG "VIDEOEDITOR_MP3READER"
     24 
     25 /**
     26  * HEADERS
     27  *
     28  */
     29 #include "M4OSA_Debug.h"
     30 #include "M4SYS_AccessUnit.h"
     31 #include "VideoEditorMp3Reader.h"
     32 #include "VideoEditorUtils.h"
     33 
     34 #include "utils/Log.h"
     35 #include <media/stagefright/foundation/ADebug.h>
     36 #include <media/stagefright/MediaBufferGroup.h>
     37 #include <media/stagefright/DataSource.h>
     38 #include <media/stagefright/FileSource.h>
     39 #include <media/stagefright/MediaBuffer.h>
     40 #include <media/stagefright/MediaDefs.h>
     41 #include <media/stagefright/MediaExtractor.h>
     42 #include <media/stagefright/MediaSource.h>
     43 #include <media/stagefright/MetaData.h>
     44 
     45 /**
     46  * SOURCE CLASS
     47  */
     48 
     49 namespace android {
     50 /**
     51  * ENGINE INTERFACE
     52  */
     53 
     54 /**
     55  **************************************************************************
     56  * structure VideoEditorMp3Reader_Context
     57  * @brief    This structure defines the context of the SF MP3 reader shell.
     58  **************************************************************************
     59  */
     60 typedef struct {
     61     sp<DataSource>              mDataSource;
     62     sp<MediaExtractor>          mExtractor;
     63     sp<MediaSource>             mMediaSource;
     64     M4_AudioStreamHandler*      mAudioStreamHandler;
     65     M4SYS_AccessUnit            mAudioAu;
     66     M4OSA_Time                  mMaxDuration;
     67     M4OSA_UInt8                 mStreamNumber;
     68     M4OSA_Bool                  mSeeking;
     69     M4OSA_Time                  mSeekTime;
     70     uint32_t                    mExtractorFlags;
     71 } VideoEditorMp3Reader_Context;
     72 
     73 /**
     74  ****************************************************************************
     75  * @brief    create an instance of the MP3 reader
     76  * @note     allocates the context
     77  *
     78  * @param    pContext:        (OUT)    pointer on a reader context
     79  *
     80  * @return    M4NO_ERROR                 there is no error
     81  * @return    M4ERR_ALLOC                a memory allocation has failed
     82  * @return    M4ERR_PARAMETER            at least one parameter is not valid
     83  ****************************************************************************
     84 */
     85 M4OSA_ERR VideoEditorMp3Reader_create(M4OSA_Context *pContext) {
     86     M4OSA_ERR err = M4NO_ERROR;
     87     VideoEditorMp3Reader_Context *pReaderContext = M4OSA_NULL;
     88 
     89     VIDEOEDITOR_CHECK(M4OSA_NULL != pContext, M4ERR_PARAMETER);
     90 
     91     ALOGV("VideoEditorMp3Reader_create begin");
     92 
     93     /* Context allocation & initialization */
     94     SAFE_MALLOC(pReaderContext, VideoEditorMp3Reader_Context, 1,
     95         "VideoEditorMp3Reader");
     96 
     97     pReaderContext->mAudioStreamHandler  = M4OSA_NULL;
     98     pReaderContext->mAudioAu.dataAddress = M4OSA_NULL;
     99     pReaderContext->mMaxDuration = 0;
    100     *pContext = pReaderContext;
    101 
    102 cleanUp:
    103     if (M4NO_ERROR == err) {
    104         ALOGV("VideoEditorMp3Reader_create no error");
    105     } else {
    106         ALOGV("VideoEditorMp3Reader_create ERROR 0x%X", err);
    107     }
    108     ALOGV("VideoEditorMp3Reader_create end");
    109     return err;
    110 }
    111 
    112 /**
    113  *******************************************************************************
    114  * @brief     destroy the instance of the MP3 reader
    115  * @note      after this call the context is invalid
    116  * @param     context:        (IN)    Context of the reader
    117  * @return    M4NO_ERROR                 there is no error
    118  * @return    M4ERR_PARAMETER            The input parameter is not properly set
    119  *******************************************************************************
    120 */
    121 M4OSA_ERR VideoEditorMp3Reader_destroy(M4OSA_Context pContext) {
    122     M4OSA_ERR err = M4NO_ERROR;
    123     VideoEditorMp3Reader_Context *pReaderContext =
    124         (VideoEditorMp3Reader_Context*)pContext;
    125 
    126     VIDEOEDITOR_CHECK(M4OSA_NULL != pReaderContext, M4ERR_PARAMETER);
    127     ALOGV("VideoEditorMp3Reader_destroy begin");
    128 
    129     SAFE_FREE(pReaderContext);
    130 cleanUp:
    131     if (M4NO_ERROR == err) {
    132         ALOGV("VideoEditorMp3Reader_destroy no error");
    133     } else {
    134         ALOGV("VideoEditorMp3Reader_destroy ERROR 0x%X", err);
    135     }
    136     ALOGV("VideoEditorMp3Reader_destroy end");
    137     return err;
    138 }
    139 /**
    140  ******************************************************************************
    141  * @brief    open the reader and initializes its created instance
    142  * @note    this function opens the MP3 file
    143  * @param    context:            (IN)    Context of the reader
    144  * @param    pFileDescriptor:    (IN)    Pointer to proprietary data identifying
    145  *                                       the media to open
    146 
    147  * @return    M4NO_ERROR                     there is no error
    148  * @return    M4ERR_PARAMETER                the context is NULL
    149  * @return    M4ERR_BAD_CONTEXT              provided context is not a valid one
    150  * @return    M4ERR_UNSUPPORTED_MEDIA_TYPE   the media is DRM protected
    151  ******************************************************************************
    152 */
    153 M4OSA_ERR VideoEditorMp3Reader_open(M4OSA_Context context,
    154         M4OSA_Void* pFileDescriptor){
    155     VideoEditorMp3Reader_Context *pReaderContext =
    156     (VideoEditorMp3Reader_Context*)context;
    157     M4OSA_ERR err = M4NO_ERROR;
    158 
    159     ALOGV("VideoEditorMp3Reader_open begin");
    160     /* Check function parameters*/
    161     M4OSA_DEBUG_IF1((M4OSA_NULL == pReaderContext),  M4ERR_PARAMETER,
    162         "VideoEditorMp3Reader_open: invalid context pointer");
    163     M4OSA_DEBUG_IF1((M4OSA_NULL == pFileDescriptor), M4ERR_PARAMETER,
    164         "VideoEditorMp3Reader_open: invalid pointer pFileDescriptor");
    165 
    166     ALOGV("VideoEditorMp3Reader_open Datasource start %s",
    167         (char*)pFileDescriptor);
    168     pReaderContext->mDataSource = new FileSource ((char*)pFileDescriptor);
    169     ALOGV("VideoEditorMp3Reader_open Datasource end");
    170 
    171     if (pReaderContext->mDataSource == NULL) {
    172         ALOGV("VideoEditorMp3Reader_open Datasource error");
    173         return UNKNOWN_ERROR;
    174     }
    175 
    176     ALOGV("VideoEditorMp3Reader_open extractor start");
    177     pReaderContext->mExtractor = MediaExtractor::Create(
    178         pReaderContext->mDataSource,MEDIA_MIMETYPE_AUDIO_MPEG);
    179     ALOGV("VideoEditorMp3Reader_open extractor end");
    180 
    181     if (pReaderContext->mExtractor == NULL)    {
    182         ALOGV("VideoEditorMp3Reader_open extractor error");
    183         return UNKNOWN_ERROR;
    184     }
    185     pReaderContext->mStreamNumber = 0;
    186 
    187     int32_t isDRMProtected = 0;
    188     sp<MetaData> meta = pReaderContext->mExtractor->getMetaData();
    189     meta->findInt32(kKeyIsDRM, &isDRMProtected);
    190     if (isDRMProtected) {
    191         ALOGV("VideoEditorMp3Reader_open error - DRM Protected");
    192         return M4ERR_UNSUPPORTED_MEDIA_TYPE;
    193     }
    194 
    195     ALOGV("VideoEditorMp3Reader_open end");
    196     return err;
    197 }
    198 /**
    199  **************************************************************************
    200  * @brief    close the reader
    201  * @note    this function closes the MP3 reader
    202  * @param    context:        (IN)      Context of the reader
    203  * @return    M4NO_ERROR               there is no error
    204  * @return    M4ERR_PARAMETER          the context is NULL
    205  **************************************************************************
    206 */
    207 M4OSA_ERR VideoEditorMp3Reader_close(M4OSA_Context context) {
    208     VideoEditorMp3Reader_Context *pReaderContext =
    209         (VideoEditorMp3Reader_Context*)context;
    210     M4OSA_ERR err = M4NO_ERROR;
    211 
    212     ALOGV("VideoEditorMp3Reader_close begin");
    213     /* Check function parameters */
    214     M4OSA_DEBUG_IF1((M4OSA_NULL == pReaderContext), M4ERR_PARAMETER,
    215             "VideoEditorMp3Reader_close: invalid context pointer");
    216 
    217     if (pReaderContext->mAudioStreamHandler != NULL) {
    218         if (M4OSA_NULL != pReaderContext->mAudioStreamHandler->\
    219         m_basicProperties.m_pDecoderSpecificInfo) {
    220             free(pReaderContext->mAudioStreamHandler->\
    221                 m_basicProperties.m_pDecoderSpecificInfo);
    222             pReaderContext->mAudioStreamHandler->m_basicProperties.\
    223                 m_decoderSpecificInfoSize = 0;
    224             pReaderContext->mAudioStreamHandler->m_basicProperties.\
    225                 m_pDecoderSpecificInfo = M4OSA_NULL;
    226         }
    227 
    228         /* Finally destroy the stream handler */
    229         free(pReaderContext->mAudioStreamHandler);
    230         pReaderContext->mAudioStreamHandler = M4OSA_NULL;
    231 
    232         if (pReaderContext->mAudioAu.dataAddress != NULL) {
    233             free(pReaderContext->mAudioAu.dataAddress);
    234             pReaderContext->mAudioAu.dataAddress = NULL;
    235         }
    236     }
    237 
    238     pReaderContext->mMediaSource->stop();
    239     pReaderContext->mMediaSource.clear();
    240     pReaderContext->mExtractor.clear();
    241     pReaderContext->mDataSource.clear();
    242 
    243     ALOGV("VideoEditorMp3Reader_close end ");
    244     return err;
    245 }
    246 /**
    247  ******************************************************************************
    248  * @brief    get an option value from the reader
    249  * @note
    250  *          it allows the caller to retrieve a property value:
    251  *
    252  * @param    context:        (IN)    Context of the reader
    253  * @param    optionId:       (IN)    indicates the option to get
    254  * @param    pValue:         (OUT)   pointer to structure or value (allocated
    255  *                                   by user) where option is stored
    256  *
    257  * @return    M4NO_ERROR             there is no error
    258  * @return    M4ERR_PARAMETER        at least one parameter is not properly set
    259  * @return    M4ERR_BAD_OPTION_ID    when the option ID is not a valid one
    260  ******************************************************************************
    261 */
    262 M4OSA_ERR VideoEditorMp3Reader_getOption(M4OSA_Context context,
    263           M4OSA_OptionID optionId, M4OSA_DataOption pValue) {
    264     VideoEditorMp3Reader_Context *pReaderContext =
    265         (VideoEditorMp3Reader_Context*)context;
    266     M4OSA_ERR err = M4NO_ERROR;
    267 
    268     ALOGV("VideoEditorMp3Reader_getOption begin: optionId= %d ",(int)optionId);
    269 
    270     M4OSA_DEBUG_IF1((M4OSA_NULL == pReaderContext), M4ERR_PARAMETER,
    271         "invalid value pointer");
    272     M4OSA_DEBUG_IF1((M4OSA_NULL == pValue), M4ERR_PARAMETER,
    273         "invalid value pointer");
    274 
    275     switch(optionId) {
    276     case M4READER_kOptionID_Duration:
    277         {
    278             ALOGV("Mp3Reader duration=%ld",pReaderContext->mMaxDuration);
    279             *(M4OSA_Time*)pValue = pReaderContext->mMaxDuration;
    280         }
    281         break;
    282 
    283     case M4READER_kOptionID_Bitrate:
    284         {
    285             M4OSA_UInt32* pBitrate = (M4OSA_UInt32*)pValue;
    286             if (M4OSA_NULL != pReaderContext->mAudioStreamHandler) {
    287                 *pBitrate = pReaderContext->mAudioStreamHandler->\
    288                     m_basicProperties.m_averageBitRate;
    289             } else {
    290                 pBitrate = 0;
    291                 err = M4ERR_PARAMETER;
    292             }
    293         }
    294         break;
    295 
    296     case M4READER_kOptionID_Mp3Id3v1Tag:
    297         break;
    298 
    299     case M4READER_kOptionID_Mp3Id3v2Tag:
    300         break;
    301 
    302     case M4READER_kOptionID_GetMetadata:
    303         break;
    304 
    305     default :
    306         {
    307             ALOGV("VideoEditorMp3Reader_getOption:  M4ERR_BAD_OPTION_ID");
    308             err = M4ERR_BAD_OPTION_ID;
    309         }
    310     }
    311     ALOGV("VideoEditorMp3Reader_getOption end ");
    312     return err;
    313 }
    314 /**
    315  ******************************************************************************
    316  * @brief   set an option value of the reader
    317  * @note
    318  *          it allows the caller to set a property value:
    319  *
    320  * @param   context:    (IN)        Context of the reader
    321  * @param   optionId:   (IN)        Identifier indicating the option to set
    322  * @param   pValue:     (IN)        Pointer to structure or value (allocated
    323  *                                  by user) where option is stored
    324  *
    325  * @return  M4NO_ERROR              There is no error
    326  * @return  M4ERR_BAD_OPTION_ID     The option ID is not a valid one
    327  * @return  M4ERR_STATE             State automaton is not applied
    328  * @return  M4ERR_PARAMETER         The option parameter is invalid
    329  ******************************************************************************
    330 */
    331 M4OSA_ERR VideoEditorMp3Reader_setOption(M4OSA_Context context,
    332         M4OSA_OptionID optionId, M4OSA_DataOption pValue) {
    333     VideoEditorMp3Reader_Context *pReaderContext =
    334         (VideoEditorMp3Reader_Context*)context;
    335     M4OSA_ERR err = M4NO_ERROR;
    336 
    337     ALOGV("VideoEditorMp3Reader_Context begin: optionId: %d Value: %d ",
    338         (int)optionId,(int)pValue);
    339 
    340     M4OSA_DEBUG_IF1((M4OSA_NULL == pReaderContext), M4ERR_PARAMETER,
    341         "invalid context pointer");
    342     M4OSA_DEBUG_IF1((M4OSA_NULL == pValue), M4ERR_PARAMETER,
    343         "invalid value pointer");
    344 
    345     switch(optionId) {
    346         case M4READER_kOptionID_SetOsaFileReaderFctsPtr:
    347         default :
    348         {
    349             err = M4NO_ERROR;
    350         }
    351     }
    352     ALOGV("VideoEditorMp3Reader_Context end ");
    353     return err;
    354 }
    355 /**
    356  ******************************************************************************
    357  * @brief    jump into the stream at the specified time
    358  * @note
    359  * @param    context:      (IN)   Context of the reader
    360  * @param    pStreamHandler(IN)   stream description of the stream to make jump
    361  * @param    pTime         (I/O)IN:the time to jump to (in ms)
    362  *                              OUT: the time to which the stream really jumped
    363  * @return    M4NO_ERROR           there is no error
    364  * @return    M4ERR_PARAMETER      at least one parameter is not properly set
    365  ******************************************************************************
    366 */
    367 M4OSA_ERR VideoEditorMp3Reader_jump(M4OSA_Context context,
    368         M4_StreamHandler *pStreamHandler, M4OSA_Int32* pTime) {
    369     VideoEditorMp3Reader_Context *pReaderContext =
    370         (VideoEditorMp3Reader_Context*)context;
    371     M4SYS_StreamID streamIdArray[2];
    372     M4OSA_ERR err = M4NO_ERROR;
    373     M4SYS_AccessUnit* pAu;
    374     M4OSA_Time time64 = (M4OSA_Time)*pTime;
    375 
    376     ALOGV("VideoEditorMp3Reader_jump begin");
    377     M4OSA_DEBUG_IF1((pReaderContext == 0), M4ERR_PARAMETER,
    378         "VideoEditorMp3Reader_jump: invalid context");
    379     M4OSA_DEBUG_IF1((pStreamHandler == 0), M4ERR_PARAMETER,
    380         "VideoEditorMp3Reader_jump: invalid pointer to M4_StreamHandler");
    381     M4OSA_DEBUG_IF1((pTime == 0), M4ERR_PARAMETER,
    382         "VideoEditorMp3Reader_jump: invalid time pointer");
    383 
    384     if(pStreamHandler == (M4_StreamHandler*)pReaderContext->\
    385         mAudioStreamHandler){
    386         pAu = &pReaderContext->mAudioAu;
    387     } else {
    388         ALOGV("VideoEditorMp3Reader_jump: passed StreamHandler is not known");
    389         return M4ERR_PARAMETER;
    390     }
    391 
    392     streamIdArray[0] = pStreamHandler->m_streamId;
    393     streamIdArray[1] = 0;
    394 
    395     ALOGV("VideoEditorMp3Reader_jump time ms %ld ", time64);
    396 
    397     pAu->CTS = time64;
    398     pAu->DTS = time64;
    399 
    400     time64 = time64 * 1000; /* Convert the time into micro sec */
    401     ALOGV("VideoEditorMp3Reader_jump time us %ld ", time64);
    402 
    403     pReaderContext->mSeeking = M4OSA_TRUE;
    404     pReaderContext->mSeekTime = time64;
    405 
    406     time64 = time64 / 1000; /* Convert the time into milli sec */
    407     *pTime = (M4OSA_Int32)time64;
    408     ALOGV("VideoEditorMp3Reader_jump end ");
    409     return err;
    410 }
    411 /**
    412  *******************************************************************************
    413  * @brief   Get the next stream found in the media file
    414  *
    415  * @param    context:        (IN)  Context of the reader
    416  * @param    pMediaFamily:   (OUT) pointer to a user allocated
    417  *                                 M4READER_MediaFamily that will be filled with
    418  *                                 the media family of the found stream
    419  * @param    pStreamHandler: (OUT) pointer to a stream handler that will be
    420  *                                 allocated and filled with stream description
    421  *
    422  * @return    M4NO_ERROR             there is no error
    423  * @return    M4WAR_NO_MORE_STREAM   no more available stream in the media
    424  * @return    M4ERR_PARAMETER        at least one parameter is not properly set
    425  *******************************************************************************
    426 */
    427 M4OSA_ERR VideoEditorMp3Reader_getNextStream(M4OSA_Context context,
    428         M4READER_MediaFamily *pMediaFamily,
    429         M4_StreamHandler **pStreamHandlerParam) {
    430     VideoEditorMp3Reader_Context *pReaderContext =
    431         (VideoEditorMp3Reader_Context*)context;
    432     M4OSA_ERR err = M4NO_ERROR;
    433     M4SYS_StreamID streamIdArray[2];
    434     M4SYS_StreamDescription streamDesc;
    435     M4_AudioStreamHandler* pAudioStreamHandler;
    436     M4_StreamHandler* pStreamHandler;
    437     M4OSA_UInt8 type, temp;
    438     M4OSA_Bool haveAudio = M4OSA_FALSE;
    439     sp<MetaData> meta = NULL;
    440     int64_t Duration;
    441 
    442     ALOGV("VideoEditorMp3Reader_getNextStream begin");
    443     M4OSA_DEBUG_IF1((pReaderContext == 0),      M4ERR_PARAMETER,
    444         "VideoEditorMp3Reader_getNextStream: invalid context");
    445     M4OSA_DEBUG_IF1((pMediaFamily == 0),        M4ERR_PARAMETER,
    446         "VideoEditorMp3Reader_getNextStream: invalid pointer to MediaFamily");
    447     M4OSA_DEBUG_IF1((pStreamHandlerParam == 0), M4ERR_PARAMETER,
    448         "VideoEditorMp3Reader_getNextStream: invalid pointer to StreamHandler");
    449 
    450     ALOGV("VideoEditorMp3Reader_getNextStream stream number = %d",
    451         pReaderContext->mStreamNumber);
    452     if (pReaderContext->mStreamNumber >= 1) {
    453         ALOGV("VideoEditorMp3Reader_getNextStream max number of stream reached");
    454         return M4WAR_NO_MORE_STREAM;
    455     }
    456     pReaderContext->mStreamNumber = pReaderContext->mStreamNumber + 1;
    457     ALOGV("VideoEditorMp3Reader_getNextStream number of Tracks%d",
    458         pReaderContext->mExtractor->countTracks());
    459     for (temp = 0; temp < pReaderContext->mExtractor->countTracks(); temp++) {
    460         meta = pReaderContext->mExtractor->getTrackMetaData(temp);
    461         const char *mime;
    462         CHECK(meta->findCString(kKeyMIMEType, &mime));
    463 
    464         if (!haveAudio && !strncasecmp(mime, "audio/", 6)) {
    465             pReaderContext->mMediaSource =
    466                 pReaderContext->mExtractor->getTrack(temp);
    467             pReaderContext->mMediaSource->start();
    468             haveAudio = true;
    469         }
    470 
    471         if (haveAudio) {
    472             break;
    473         }
    474     }
    475 
    476     if (!haveAudio) {
    477         ALOGV("VideoEditorMp3Reader_getNextStream no more stream ");
    478         pReaderContext->mDataSource.clear();
    479         return M4WAR_NO_MORE_STREAM;
    480     }
    481 
    482     pReaderContext->mExtractorFlags = pReaderContext->mExtractor->flags();
    483     *pMediaFamily = M4READER_kMediaFamilyAudio;
    484 
    485     streamDesc.duration = meta->findInt64(kKeyDuration, &Duration);
    486     streamDesc.duration = (M4OSA_Time)Duration/1000;
    487 
    488     meta->findInt32(kKeyBitRate, (int32_t*)&streamDesc.averageBitrate);
    489     meta->findInt32(kKeySampleRate, (int32_t*)&streamDesc.timeScale);
    490     ALOGV("Bitrate = %d, SampleRate = %d duration = %lld",
    491         streamDesc.averageBitrate,streamDesc.timeScale,Duration/1000);
    492 
    493     streamDesc.streamType = M4SYS_kMP3;
    494     streamDesc.profileLevel = 0xFF ;
    495     streamDesc.streamID = pReaderContext->mStreamNumber;
    496     streamDesc.decoderSpecificInfo = M4OSA_NULL;
    497     streamDesc.decoderSpecificInfoSize = 0;
    498     streamDesc.maxBitrate = streamDesc.averageBitrate;
    499 
    500     /*    Allocate the audio stream handler and set its parameters    */
    501     pAudioStreamHandler = (M4_AudioStreamHandler*)M4OSA_32bitAlignedMalloc(
    502         sizeof(M4_AudioStreamHandler), M4READER_MP3,
    503         (M4OSA_Char*)"M4_AudioStreamHandler");
    504 
    505     if (pAudioStreamHandler == M4OSA_NULL) {
    506         ALOGV("VideoEditorMp3Reader_getNextStream malloc failed");
    507         pReaderContext->mMediaSource->stop();
    508         pReaderContext->mMediaSource.clear();
    509         pReaderContext->mDataSource.clear();
    510 
    511         return M4ERR_ALLOC;
    512     }
    513     pStreamHandler =(M4_StreamHandler*)(pAudioStreamHandler);
    514     *pStreamHandlerParam = pStreamHandler;
    515     pReaderContext->mAudioStreamHandler = pAudioStreamHandler;
    516 
    517     pAudioStreamHandler->m_structSize = sizeof(M4_AudioStreamHandler);
    518 
    519     if (meta == NULL) {
    520         ALOGV("VideoEditorMp3Reader_getNextStream meta is NULL");
    521     }
    522 
    523     pAudioStreamHandler->m_samplingFrequency = streamDesc.timeScale;
    524     pStreamHandler->m_pDecoderSpecificInfo =
    525         (M4OSA_UInt8*)(streamDesc.decoderSpecificInfo);
    526     pStreamHandler->m_decoderSpecificInfoSize =
    527         streamDesc.decoderSpecificInfoSize;
    528 
    529     meta->findInt32(kKeyChannelCount,
    530         (int32_t*)&pAudioStreamHandler->m_nbChannels);
    531     pAudioStreamHandler->m_byteFrameLength = 1152;
    532     pAudioStreamHandler->m_byteSampleSize = 2;
    533 
    534     pStreamHandler->m_pUserData = NULL;
    535     pStreamHandler->m_streamId = streamDesc.streamID;
    536     pStreamHandler->m_duration = streamDesc.duration;
    537     pReaderContext->mMaxDuration = streamDesc.duration;
    538     pStreamHandler->m_averageBitRate = streamDesc.averageBitrate;
    539 
    540     pStreamHandler->m_maxAUSize = 0;
    541     pStreamHandler->m_streamType = M4DA_StreamTypeAudioMp3;
    542 
    543     ALOGV("VideoEditorMp3Reader_getNextStream end ");
    544     return err;
    545 }
    546 
    547 /**
    548  *******************************************************************************
    549  * @brief    fill the access unit structure with initialization values
    550  * @param    context:        (IN)     Context of the reader
    551  * @param    pStreamHandler: (IN)     pointer to the stream handler to which
    552  *                                    the access unit will be associated
    553  * @param    pAccessUnit:    (IN/OUT) pointer to the access unit (allocated by
    554  *                                    the caller) to initialize
    555  * @return   M4NO_ERROR               there is no error
    556  * @return   M4ERR_PARAMETER          at least one parameter is not properly set
    557  *******************************************************************************
    558 */
    559 M4OSA_ERR VideoEditorMp3Reader_fillAuStruct(M4OSA_Context context,
    560         M4_StreamHandler *pStreamHandler, M4_AccessUnit *pAccessUnit) {
    561     VideoEditorMp3Reader_Context *pReaderContext =
    562         (VideoEditorMp3Reader_Context*)context;
    563     M4SYS_AccessUnit *pAu;
    564 
    565     M4OSA_DEBUG_IF1((pReaderContext == 0), M4ERR_PARAMETER,
    566         "VideoEditorMp3Reader_fillAuStruct: invalid context");
    567     M4OSA_DEBUG_IF1((pStreamHandler == 0), M4ERR_PARAMETER,
    568         "VideoEditorMp3Reader_fillAuStruct invalid pointer to StreamHandler");
    569     M4OSA_DEBUG_IF1((pAccessUnit == 0),    M4ERR_PARAMETER,
    570         "VideoEditorMp3Reader_fillAuStruct: invalid pointer to M4_AccessUnit");
    571 
    572     ALOGV("VideoEditorMp3Reader_fillAuStruct start ");
    573     if(pStreamHandler == (M4_StreamHandler*)pReaderContext->\
    574         mAudioStreamHandler){
    575         pAu = &pReaderContext->mAudioAu;
    576     } else {
    577         ALOGV("VideoEditorMp3Reader_fillAuStruct StreamHandler is not known");
    578         return M4ERR_PARAMETER;
    579     }
    580 
    581     /* Initialize pAu structure */
    582     pAu->dataAddress = M4OSA_NULL;
    583     pAu->size        = 0;
    584     pAu->CTS         = 0;
    585     pAu->DTS         = 0;
    586     pAu->attribute   = 0;
    587     pAu->nbFrag      = 0;
    588 
    589     /* Initialize pAccessUnit structure */
    590     pAccessUnit->m_size         = 0;
    591     pAccessUnit->m_CTS          = 0;
    592     pAccessUnit->m_DTS          = 0;
    593     pAccessUnit->m_attribute    = 0;
    594     pAccessUnit->m_dataAddress  = M4OSA_NULL;
    595     pAccessUnit->m_maxsize      = pStreamHandler->m_maxAUSize;
    596     pAccessUnit->m_streamID     = pStreamHandler->m_streamId;
    597     pAccessUnit->m_structSize   = sizeof(M4_AccessUnit);
    598 
    599     ALOGV("VideoEditorMp3Reader_fillAuStruct end");
    600     return M4NO_ERROR;
    601 }
    602 
    603 /**
    604  *******************************************************************************
    605  * @brief    reset the stream, i.e seek it to the beginning
    606  * @note
    607  * @param     context:          (IN)  Context of the reader
    608  * @param     pStreamHandler    (IN)  The stream handler of the stream to reset
    609  * @return    M4NO_ERROR              there is no error
    610  * @return    M4ERR_PARAMETER         at least one parameter is not properly set
    611  *******************************************************************************
    612 */
    613 M4OSA_ERR VideoEditorMp3Reader_reset(M4OSA_Context context,
    614         M4_StreamHandler *pStreamHandler) {
    615     VideoEditorMp3Reader_Context *pReaderContext =
    616         (VideoEditorMp3Reader_Context*)context;
    617 
    618     M4OSA_ERR err = M4NO_ERROR;
    619     M4SYS_StreamID streamIdArray[2];
    620     M4SYS_AccessUnit* pAu;
    621     M4OSA_Time time64 = 0;
    622 
    623     ALOGV("VideoEditorMp3Reader_reset start");
    624     M4OSA_DEBUG_IF1((pReaderContext == 0), M4ERR_PARAMETER,
    625         "VideoEditorMp3Reader_reset: invalid context");
    626     M4OSA_DEBUG_IF1((pStreamHandler == 0), M4ERR_PARAMETER,
    627         "VideoEditorMp3Reader_reset: invalid pointer to M4_StreamHandler");
    628 
    629     if (pStreamHandler == (M4_StreamHandler*)pReaderContext->\
    630         mAudioStreamHandler) {
    631         pAu = &pReaderContext->mAudioAu;
    632     } else {
    633         ALOGV("VideoEditorMp3Reader_reset StreamHandler is not known");
    634         return M4ERR_PARAMETER;
    635     }
    636     streamIdArray[0] = pStreamHandler->m_streamId;
    637     streamIdArray[1] = 0;
    638     pAu->CTS = time64;
    639     pAu->DTS = time64;
    640 
    641     pReaderContext->mSeeking = M4OSA_TRUE;
    642     pReaderContext->mSeekTime = time64;
    643 
    644     ALOGV("VideoEditorMp3Reader_reset end");
    645     return err;
    646 }
    647 /**
    648  *******************************************************************************
    649  * @brief   Gets an access unit (AU) from the stream handler source.
    650  * @note    AU is the smallest possible amount of data to be decoded by decoder
    651  *
    652  * @param   context:       (IN) Context of the reader
    653  * @param   pStreamHandler (IN) The stream handler of the stream to make jump
    654  * @param   pAccessUnit    (I/O)Pointer to an access unit to fill with read data
    655  * @return    M4NO_ERROR        there is no error
    656  * @return    M4ERR_PARAMETER   at least one parameter is not properly set
    657  * @returns   M4ERR_ALLOC       memory allocation failed
    658  * @returns   M4WAR_NO_MORE_AU  there are no more access unit in the stream
    659  *******************************************************************************
    660 */
    661 M4OSA_ERR VideoEditorMp3Reader_getNextAu(M4OSA_Context context,
    662         M4_StreamHandler *pStreamHandler, M4_AccessUnit *pAccessUnit) {
    663     VideoEditorMp3Reader_Context *pReaderContext =
    664         (VideoEditorMp3Reader_Context*)context;
    665     M4OSA_ERR err = M4NO_ERROR;
    666     M4SYS_AccessUnit* pAu;
    667     MediaBuffer *mAudioBuffer;
    668     MediaSource::ReadOptions options;
    669 
    670     ALOGV("VideoEditorMp3Reader_getNextAu start");
    671     M4OSA_DEBUG_IF1((pReaderContext == 0), M4ERR_PARAMETER,
    672         "VideoEditorMp3Reader_getNextAu: invalid context");
    673     M4OSA_DEBUG_IF1((pStreamHandler == 0), M4ERR_PARAMETER,
    674         "VideoEditorMp3Reader_getNextAu: invalid pointer to M4_StreamHandler");
    675     M4OSA_DEBUG_IF1((pAccessUnit == 0),    M4ERR_PARAMETER,
    676         "VideoEditorMp3Reader_getNextAu: invalid pointer to M4_AccessUnit");
    677 
    678     if (pStreamHandler == (M4_StreamHandler*)pReaderContext->\
    679         mAudioStreamHandler) {
    680         pAu = &pReaderContext->mAudioAu;
    681     } else {
    682         ALOGV("VideoEditorMp3Reader_getNextAu: StreamHandler is not known\n");
    683         return M4ERR_PARAMETER;
    684     }
    685 
    686     if (pReaderContext->mSeeking) {
    687         options.setSeekTo(pReaderContext->mSeekTime);
    688     }
    689 
    690     pReaderContext->mMediaSource->read(&mAudioBuffer, &options);
    691 
    692     if (mAudioBuffer != NULL) {
    693         if ((pAu->dataAddress == NULL) ||
    694             (pAu->size < mAudioBuffer->range_length())) {
    695             if (pAu->dataAddress != NULL) {
    696                 free((M4OSA_Int32*)pAu->dataAddress);
    697                 pAu->dataAddress = NULL;
    698             }
    699             pAu->dataAddress = (M4OSA_Int32*)M4OSA_32bitAlignedMalloc(
    700                 (mAudioBuffer->range_length() + 3) & ~0x3,
    701                 M4READER_MP3, (M4OSA_Char*)"pAccessUnit->m_dataAddress" );
    702 
    703             if (pAu->dataAddress == NULL) {
    704                 ALOGV("VideoEditorMp3Reader_getNextAu malloc failed");
    705                 pReaderContext->mMediaSource->stop();
    706                 pReaderContext->mMediaSource.clear();
    707                 pReaderContext->mDataSource.clear();
    708 
    709                 return M4ERR_ALLOC;
    710             }
    711         }
    712         pAu->size = mAudioBuffer->range_length();
    713         memcpy((M4OSA_MemAddr8)pAu->dataAddress,
    714             (const char *)mAudioBuffer->data() + mAudioBuffer->range_offset(),
    715             mAudioBuffer->range_length());
    716 
    717         mAudioBuffer->meta_data()->findInt64(kKeyTime, (int64_t*)&pAu->CTS);
    718 
    719 
    720         pAu->CTS = pAu->CTS / 1000; /*converting the microsec to millisec */
    721         pAu->DTS  = pAu->CTS;
    722         pAu->attribute = M4SYS_kFragAttrOk;
    723         mAudioBuffer->release();
    724 
    725         ALOGV("VideoEditorMp3Reader_getNextAu AU CTS = %ld",pAu->CTS);
    726 
    727         pAccessUnit->m_dataAddress = (M4OSA_Int8*) pAu->dataAddress;
    728         pAccessUnit->m_size = pAu->size;
    729         pAccessUnit->m_CTS = pAu->CTS;
    730         pAccessUnit->m_DTS = pAu->DTS;
    731         pAccessUnit->m_attribute = pAu->attribute;
    732     } else {
    733         ALOGV("VideoEditorMp3Reader_getNextAu EOS reached.");
    734         pAccessUnit->m_size=0;
    735         err = M4WAR_NO_MORE_AU;
    736     }
    737     pAu->nbFrag = 0;
    738 
    739     options.clearSeekTo();
    740     pReaderContext->mSeeking = M4OSA_FALSE;
    741     mAudioBuffer = NULL;
    742     ALOGV("VideoEditorMp3Reader_getNextAu end");
    743 
    744     return err;
    745 }
    746 
    747 extern "C" {
    748 
    749 M4OSA_ERR VideoEditorMp3Reader_getInterface(
    750         M4READER_MediaType *pMediaType,
    751         M4READER_GlobalInterface **pRdrGlobalInterface,
    752         M4READER_DataInterface **pRdrDataInterface) {
    753     M4OSA_ERR err = M4NO_ERROR;
    754 
    755     ALOGV("VideoEditorMp3Reader_getInterface: begin");
    756     /* Input parameters check */
    757     VIDEOEDITOR_CHECK(M4OSA_NULL != pMediaType,      M4ERR_PARAMETER);
    758     VIDEOEDITOR_CHECK(M4OSA_NULL != pRdrGlobalInterface, M4ERR_PARAMETER);
    759     VIDEOEDITOR_CHECK(M4OSA_NULL != pRdrDataInterface, M4ERR_PARAMETER);
    760 
    761     SAFE_MALLOC(*pRdrGlobalInterface, M4READER_GlobalInterface, 1,
    762         "VideoEditorMp3Reader_getInterface");
    763     SAFE_MALLOC(*pRdrDataInterface, M4READER_DataInterface, 1,
    764         "VideoEditorMp3Reader_getInterface");
    765 
    766     *pMediaType = M4READER_kMediaTypeMP3;
    767 
    768     (*pRdrGlobalInterface)->m_pFctCreate       = VideoEditorMp3Reader_create;
    769     (*pRdrGlobalInterface)->m_pFctDestroy      = VideoEditorMp3Reader_destroy;
    770     (*pRdrGlobalInterface)->m_pFctOpen         = VideoEditorMp3Reader_open;
    771     (*pRdrGlobalInterface)->m_pFctClose        = VideoEditorMp3Reader_close;
    772     (*pRdrGlobalInterface)->m_pFctGetOption    = VideoEditorMp3Reader_getOption;
    773     (*pRdrGlobalInterface)->m_pFctSetOption    = VideoEditorMp3Reader_setOption;
    774     (*pRdrGlobalInterface)->m_pFctGetNextStream =
    775         VideoEditorMp3Reader_getNextStream;
    776     (*pRdrGlobalInterface)->m_pFctFillAuStruct =
    777         VideoEditorMp3Reader_fillAuStruct;
    778     (*pRdrGlobalInterface)->m_pFctStart        = M4OSA_NULL;
    779     (*pRdrGlobalInterface)->m_pFctStop         = M4OSA_NULL;
    780     (*pRdrGlobalInterface)->m_pFctJump         = VideoEditorMp3Reader_jump;
    781     (*pRdrGlobalInterface)->m_pFctReset        = VideoEditorMp3Reader_reset;
    782     (*pRdrGlobalInterface)->m_pFctGetPrevRapTime = M4OSA_NULL;
    783 
    784     (*pRdrDataInterface)->m_pFctGetNextAu      = VideoEditorMp3Reader_getNextAu;
    785     (*pRdrDataInterface)->m_readerContext      = M4OSA_NULL;
    786 
    787 cleanUp:
    788     if( M4NO_ERROR == err )
    789     {
    790         ALOGV("VideoEditorMp3Reader_getInterface no error");
    791     }
    792     else
    793     {
    794         SAFE_FREE(*pRdrGlobalInterface);
    795         SAFE_FREE(*pRdrDataInterface);
    796 
    797         ALOGV("VideoEditorMp3Reader_getInterface ERROR 0x%X", err);
    798     }
    799     ALOGV("VideoEditorMp3Reader_getInterface: end");
    800     return err;
    801 }
    802 }  /* extern "C" */
    803 }  /* namespace android */
    804