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