VideoEditorMp3Reader.cpp revision b5c7784c96a606890eb8a8b560153ef4a5d1a0d9
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/MediaBufferGroup.h>
36#include <media/stagefright/DataSource.h>
37#include <media/stagefright/FileSource.h>
38#include <media/stagefright/MediaBuffer.h>
39#include <media/stagefright/MediaDefs.h>
40#include <media/stagefright/MediaExtractor.h>
41#include <media/stagefright/MediaDebug.h>
42#include <media/stagefright/MediaSource.h>
43#include <media/stagefright/MetaData.h>
44
45/**
46 * SOURCE CLASS
47 */
48
49namespace 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 */
60typedef 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*/
85M4OSA_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    LOGV("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
102cleanUp:
103    if (M4NO_ERROR == err) {
104        LOGV("VideoEditorMp3Reader_create no error");
105    } else {
106        LOGV("VideoEditorMp3Reader_create ERROR 0x%X", err);
107    }
108    LOGV("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*/
121M4OSA_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    LOGV("VideoEditorMp3Reader_destroy begin");
128
129    SAFE_FREE(pReaderContext);
130cleanUp:
131    if (M4NO_ERROR == err) {
132        LOGV("VideoEditorMp3Reader_destroy no error");
133    } else {
134        LOGV("VideoEditorMp3Reader_destroy ERROR 0x%X", err);
135    }
136    LOGV("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*/
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 = new FileSource ((char*)pFileDescriptor);
169    LOGV("VideoEditorMp3Reader_open Datasource end");
170
171    if (pReaderContext->mDataSource == NULL) {
172        LOGV("VideoEditorMp3Reader_open Datasource error");
173        return UNKNOWN_ERROR;
174    }
175
176    LOGV("VideoEditorMp3Reader_open extractor start");
177    pReaderContext->mExtractor = MediaExtractor::Create(
178        pReaderContext->mDataSource,MEDIA_MIMETYPE_AUDIO_MPEG);
179    LOGV("VideoEditorMp3Reader_open extractor end");
180
181    if (pReaderContext->mExtractor == NULL)    {
182        LOGV("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        LOGV("VideoEditorMp3Reader_open error - DRM Protected");
192        return M4ERR_UNSUPPORTED_MEDIA_TYPE;
193    }
194
195    LOGV("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*/
207M4OSA_ERR VideoEditorMp3Reader_close(M4OSA_Context context) {
208    VideoEditorMp3Reader_Context *pReaderContext =
209        (VideoEditorMp3Reader_Context*)context;
210    M4OSA_ERR err = M4NO_ERROR;
211
212    LOGV("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    LOGV("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*/
262M4OSA_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    LOGV("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            LOGV("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            LOGV("VideoEditorMp3Reader_getOption:  M4ERR_BAD_OPTION_ID");
308            err = M4ERR_BAD_OPTION_ID;
309        }
310    }
311    LOGV("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*/
331M4OSA_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    LOGV("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    LOGV("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*/
367M4OSA_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    LOGV("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        LOGV("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    LOGV("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    LOGV("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    LOGV("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*/
427M4OSA_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    LOGV("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    LOGV("VideoEditorMp3Reader_getNextStream stream number = %d",
451        pReaderContext->mStreamNumber);
452    if (pReaderContext->mStreamNumber >= 1) {
453        LOGV("VideoEditorMp3Reader_getNextStream max number of stream reached");
454        return M4WAR_NO_MORE_STREAM;
455    }
456    pReaderContext->mStreamNumber = pReaderContext->mStreamNumber + 1;
457    LOGV("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        LOGV("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    LOGV("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        LOGV("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        LOGV("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    LOGV("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*/
559M4OSA_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    LOGV("VideoEditorMp3Reader_fillAuStruct start ");
573    if(pStreamHandler == (M4_StreamHandler*)pReaderContext->\
574        mAudioStreamHandler){
575        pAu = &pReaderContext->mAudioAu;
576    } else {
577        LOGV("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    LOGV("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*/
613M4OSA_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    LOGV("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        LOGV("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    LOGV("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*/
661M4OSA_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    LOGV("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        LOGV("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                LOGV("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        LOGV("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        LOGV("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    LOGV("VideoEditorMp3Reader_getNextAu end");
743
744    return err;
745}
746
747extern "C" {
748
749M4OSA_ERR VideoEditorMp3Reader_getInterface(
750        M4READER_MediaType *pMediaType,
751        M4READER_GlobalInterface **pRdrGlobalInterface,
752        M4READER_DataInterface **pRdrDataInterface) {
753    M4OSA_ERR err = M4NO_ERROR;
754
755    LOGV("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
787cleanUp:
788    if( M4NO_ERROR == err )
789    {
790        LOGV("VideoEditorMp3Reader_getInterface no error");
791    }
792    else
793    {
794        SAFE_FREE(*pRdrGlobalInterface);
795        SAFE_FREE(*pRdrDataInterface);
796
797        LOGV("VideoEditorMp3Reader_getInterface ERROR 0x%X", err);
798    }
799    LOGV("VideoEditorMp3Reader_getInterface: end");
800    return err;
801}
802}  /* extern "C" */
803}  /* namespace android */
804