VideoEditor3gpReader.cpp revision aa382f3637a68361989d5b70e3184bddcc472d3d
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   VideoEditor3gpReader.cpp
20* @brief  StageFright shell 3GP Reader
21*************************************************************************
22*/
23
24#define LOG_NDEBUG 1
25#define LOG_TAG "VIDEOEDITOR_3GPREADER"
26
27/**
28 * HEADERS
29 *
30 */
31#define VIDEOEDITOR_BITSTREAM_PARSER
32
33#include "M4OSA_Debug.h"
34#include "VideoEditor3gpReader.h"
35#include "M4SYS_AccessUnit.h"
36#include "VideoEditorUtils.h"
37#include "M4READER_3gpCom.h"
38#include "M4_Common.h"
39#include "M4OSA_FileWriter.h"
40
41#ifdef VIDEOEDITOR_BITSTREAM_PARSER
42#include "M4OSA_CoreID.h"
43#include "M4OSA_Error.h"
44#include "M4OSA_Memory.h"
45#include "M4_Utils.h"
46#endif
47
48#include "ESDS.h"
49#include "utils/Log.h"
50#include <media/stagefright/MediaBufferGroup.h>
51#include <media/stagefright/DataSource.h>
52#include <media/stagefright/FileSource.h>
53#include <media/stagefright/MediaBuffer.h>
54#include <media/stagefright/MediaDefs.h>
55#include <media/stagefright/MediaExtractor.h>
56#include <media/stagefright/MediaDebug.h>
57#include <media/stagefright/MediaSource.h>
58#include <media/stagefright/MetaData.h>
59
60/**
61 * SOURCE CLASS
62 */
63namespace android {
64/**
65 * ENGINE INTERFACE
66 */
67
68/**
69 ************************************************************************
70 * @brief   Array of AMR NB/WB bitrates
71 * @note    Array to match the mode and the bit rate
72 ************************************************************************
73*/
74const M4OSA_UInt32 VideoEditor3gpReader_AmrBitRate [2 /* 8kHz / 16kHz     */]
75                                                   [9 /* the bitrate mode */] =
76{
77    {4750, 5150, 5900,  6700,  7400,  7950,  10200, 12200, 0},
78    {6600, 8850, 12650, 14250, 15850, 18250, 19850, 23050, 23850}
79};
80
81/**
82 *******************************************************************************
83 * structure VideoEditor3gpReader_Context
84 * @brief:This structure defines the context of the StageFright 3GP shell Reader
85 *******************************************************************************
86*/
87typedef struct {
88    sp<DataSource>              mDataSource;
89    sp<MediaExtractor>          mExtractor;
90    sp<MediaSource>             mAudioSource;
91    sp<MediaSource>             mVideoSource;
92    M4_StreamHandler*           mAudioStreamHandler;
93    M4_StreamHandler*           mVideoStreamHandler;
94    M4SYS_AccessUnit            mAudioAu;
95    M4SYS_AccessUnit            mVideoAu;
96    M4OSA_Time                  mMaxDuration;
97    int32_t                     mFileSize;
98    M4_StreamType               mStreamType;
99    M4OSA_UInt32                mStreamId;
100    int32_t                     mTracks;
101    int32_t                     mCurrTrack;
102    M4OSA_Bool                  mAudioSeeking;
103    M4OSA_Time                  mAudioSeekTime;
104    M4OSA_Bool                  mVideoSeeking;
105    M4OSA_Time                  mVideoSeekTime;
106
107} VideoEditor3gpReader_Context;
108
109#ifdef VIDEOEDITOR_BITSTREAM_PARSER
110/**
111 ************************************************************************
112 * structure    VideoEditor3gpReader_BitStreamParserContext
113 * @brief       Internal BitStreamParser context
114 ************************************************************************
115*/
116typedef struct {
117    M4OSA_UInt32*   mPbitStream;   /**< bitstream pointer (32bits aligned) */
118    M4OSA_Int32     mSize;         /**< bitstream size in bytes */
119    M4OSA_Int32     mIndex;        /**< byte index */
120    M4OSA_Int32     mBitIndex;     /**< bit index */
121    M4OSA_Int32     mStructSize;   /**< size of structure */
122} VideoEditor3gpReader_BitStreamParserContext;
123
124/**
125 *******************************************************************************
126 * @brief   Allocates the context and initializes internal data.
127 * @param   pContext    (OUT)  Pointer to the BitStreamParser context to create.
128 * @param   bitStream   A pointer to the bitstream
129 * @param   size        The size of the bitstream in bytes
130 *******************************************************************************
131*/
132static void VideoEditor3gpReader_BitStreamParserInit(void** pContext,
133        void* pBitStream, M4OSA_Int32 size) {
134    VideoEditor3gpReader_BitStreamParserContext* pStreamContext;
135
136    *pContext=M4OSA_NULL;
137    pStreamContext = (VideoEditor3gpReader_BitStreamParserContext*)M4OSA_32bitAlignedMalloc(
138        sizeof(VideoEditor3gpReader_BitStreamParserContext), M4READER_3GP,
139            (M4OSA_Char*)"3GP BitStreamParser Context");
140    if (M4OSA_NULL == pStreamContext) {
141        return;
142    }
143    pStreamContext->mPbitStream=(M4OSA_UInt32*)pBitStream;
144    pStreamContext->mSize=size;
145    pStreamContext->mIndex=0;
146    pStreamContext->mBitIndex=0;
147    pStreamContext->mStructSize =
148        sizeof(VideoEditor3gpReader_BitStreamParserContext);
149
150    *pContext=pStreamContext;
151}
152/**
153 **********************************************************************
154 * @brief   Clean up context
155 * @param   pContext    (IN/OUT)  BitStreamParser context.
156 **********************************************************************
157*/
158static void VideoEditor3gpReader_BitStreamParserCleanUp(void* pContext) {
159    free((M4OSA_Int32*)pContext);
160}
161/**
162 *****************************************************************************
163 * @brief   Read the next <length> bits in the bitstream.
164 * @note    The function does not update the bitstream pointer.
165 * @param   pContext    (IN/OUT) BitStreamParser context.
166 * @param   length      (IN) The number of bits to extract from the bitstream
167 * @return  the read bits
168 *****************************************************************************
169*/
170static M4OSA_UInt32 VideoEditor3gpReader_BitStreamParserShowBits(void* pContext,
171        M4OSA_Int32 length) {
172    VideoEditor3gpReader_BitStreamParserContext* pStreamContext =
173        (VideoEditor3gpReader_BitStreamParserContext*)pContext;
174
175    M4OSA_UInt32 u_mask;
176    M4OSA_UInt32 retval;
177    M4OSA_Int32 i_ovf;
178
179    M4OSA_DEBUG_IF1((M4OSA_NULL==pStreamContext), 0,
180        "VideoEditor3gpReader_BitStreamParserShowBits:invalid context pointer");
181
182    retval=(M4OSA_UInt32)GET_MEMORY32(pStreamContext->\
183        mPbitStream[ pStreamContext->mIndex ]);
184    i_ovf = pStreamContext->mBitIndex + length - 32;
185    u_mask = (length >= 32) ? 0xffffffff: (1 << length) - 1;
186
187    /* do we have enough bits availble in the current word(32bits)*/
188    if (i_ovf <= 0) {
189        retval=(retval >> (- i_ovf)) & u_mask;
190    } else {
191        M4OSA_UInt32 u_nextword = (M4OSA_UInt32)GET_MEMORY32(
192            pStreamContext->mPbitStream[ pStreamContext->mIndex + 1 ]);
193        M4OSA_UInt32 u_msb_mask, u_msb_value, u_lsb_mask, u_lsb_value;
194
195        u_msb_mask = ((1 << (32 - pStreamContext->mBitIndex)) - 1) << i_ovf;
196        u_msb_value = retval << i_ovf;
197        u_lsb_mask = (1 << i_ovf) - 1;
198        u_lsb_value = u_nextword >> (32 - i_ovf);
199        retval= (u_msb_value & u_msb_mask ) | (u_lsb_value & u_lsb_mask);
200    }
201    /* return the bits...*/
202    return retval;
203}
204/**
205 ************************************************************************
206 * @brief   Increment the bitstream pointer of <length> bits.
207 * @param   pContext    (IN/OUT) BitStreamParser context.
208 * @param   length      (IN) The number of bit to shift the bitstream
209 ************************************************************************
210*/
211static void VideoEditor3gpReader_BitStreamParserFlushBits(void* pContext,
212        M4OSA_Int32 length) {
213    VideoEditor3gpReader_BitStreamParserContext* pStreamContext=(
214        VideoEditor3gpReader_BitStreamParserContext*)pContext;
215    M4OSA_Int32 val;
216
217    if (M4OSA_NULL == pStreamContext) {
218        return;
219    }
220    val=pStreamContext->mBitIndex + length;
221    /* update the bits...*/
222    pStreamContext->mBitIndex += length;
223
224    if (val - 32 >= 0) {
225        /* update the bits...*/
226        pStreamContext->mBitIndex -= 32;
227        /* update the words*/
228        pStreamContext->mIndex++;
229    }
230}
231
232static M4OSA_UInt32 VideoEditor3gpReader_BitStreamParserGetBits(
233        void* pContext,M4OSA_Int32 bitPos, M4OSA_Int32 bitLength) {
234    VideoEditor3gpReader_BitStreamParserContext* pStreamContext =
235        (VideoEditor3gpReader_BitStreamParserContext*)pContext;
236
237    M4OSA_Int32 bitLocation, bitIndex;
238    M4OSA_UInt32 retval=0;
239
240    M4OSA_DEBUG_IF1((M4OSA_NULL==pStreamContext), 0,
241        "VideoEditor3gpReader_BitStreamParserGetBits: invalid context pointer");
242
243    /* computes the word location*/
244    bitLocation=bitPos/32;
245    bitIndex=(bitPos) % 32;
246
247    if (bitLocation < pStreamContext->mSize) {
248        M4OSA_UInt32 u_mask;
249        M4OSA_Int32 i_ovf = bitIndex + bitLength - 32;
250        retval=(M4OSA_UInt32)GET_MEMORY32(
251            pStreamContext->mPbitStream[ bitLocation ]);
252
253        u_mask = (bitLength >= 32) ? 0xffffffff: (1 << bitLength) - 1;
254
255        if (i_ovf <= 0) {
256            retval=(retval >> (- i_ovf)) & u_mask;
257        } else {
258            M4OSA_UInt32 u_nextword = (M4OSA_UInt32)GET_MEMORY32(
259                pStreamContext->mPbitStream[ bitLocation + 1 ]);
260            M4OSA_UInt32 u_msb_mask, u_msb_value, u_lsb_mask, u_lsb_value;
261
262            u_msb_mask = ((1 << (32 - bitIndex)) - 1) << i_ovf;
263            u_msb_value = retval << i_ovf;
264            u_lsb_mask = (1 << i_ovf) - 1;
265            u_lsb_value = u_nextword >> (32 - i_ovf);
266            retval= (u_msb_value & u_msb_mask ) | (u_lsb_value & u_lsb_mask);
267        }
268    }
269    return retval;
270}
271
272static void VideoEditor3gpReader_BitStreamParserRestart(void* pContext) {
273    VideoEditor3gpReader_BitStreamParserContext* pStreamContext =
274        (VideoEditor3gpReader_BitStreamParserContext*)pContext;
275
276    if (M4OSA_NULL == pStreamContext) {
277        return;
278    }
279    /* resets the bitstream pointers*/
280    pStreamContext->mIndex=0;
281    pStreamContext->mBitIndex=0;
282}
283/**
284 *******************************************************************************
285 * @brief  Get a pointer to the current byte pointed by the bitstream pointer.
286 * @note   It should be used carefully as the pointer is in the bitstream itself
287 *         and no copy is made.
288 * @param  pContext    (IN/OUT)  BitStreamParser context.
289 * @return Pointer to the current location in the bitstream
290 *******************************************************************************
291*/
292static M4OSA_UInt8*  VideoEditor3gpReader_GetCurrentbitStreamPointer(
293        void* pContext) {
294    VideoEditor3gpReader_BitStreamParserContext* pStreamContext =
295        (VideoEditor3gpReader_BitStreamParserContext*)pContext;
296    M4OSA_DEBUG_IF1((M4OSA_NULL==pStreamContext), 0, "invalid context pointer");
297
298    return (M4OSA_UInt8*)((M4OSA_UInt8*)pStreamContext->mPbitStream + \
299        pStreamContext->mIndex * sizeof(M4OSA_UInt32) + \
300        pStreamContext->mBitIndex/8) ;
301}
302
303static M4OSA_Int32 VideoEditor3gpReader_BitStreamParserGetSize(void* pContext) {
304    VideoEditor3gpReader_BitStreamParserContext* pStreamContext =
305        (VideoEditor3gpReader_BitStreamParserContext*)pContext;
306    M4OSA_DEBUG_IF1((M4OSA_NULL==pStreamContext), 0, "invalid context pointer");
307
308    return pStreamContext->mSize;
309}
310
311
312static void VideoEditor3gpReader_MPEG4BitStreamParserInit(void** pContext,
313        void* pBitStream, M4OSA_Int32 size) {
314    VideoEditor3gpReader_BitStreamParserInit(pContext, pBitStream, size);
315}
316static M4OSA_Int32 VideoEditor3gpReader_GetMpegLengthFromInteger(void* pContext,
317        M4OSA_UInt32 val) {
318    M4OSA_UInt32 length=0;
319    M4OSA_UInt32 numBytes=0;
320    M4OSA_UInt32 b=0;
321
322    M4OSA_DEBUG_IF1((M4OSA_NULL==pContext), 0, "invalid context pointer");
323
324    /* the length is encoded as a sequence of bytes. The highest bit is used
325    to indicate that the length continues on the next byte.
326
327    The length can be: 0x80 0x80 0x80 0x22
328    of just            0x22 (highest bit not set)
329
330    */
331
332    do {
333        b=(val & ((0xff)<< (8 * numBytes)))>> (8 * numBytes);
334        length=(length << 7) | (b & 0x7f);
335        numBytes++;
336    } while ((b & 0x80) && numBytes < 4);
337
338    return length;
339}
340
341/**
342 *******************************************************************************
343 * @brief  Decode an MPEG4 Systems descriptor size from an encoded SDL size data
344 * @note   The value is read from the current bitstream location.
345 * @param  pContext    (IN/OUT)  BitStreamParser context.
346 * @return Size in a human readable form
347 *******************************************************************************
348*/
349static M4OSA_Int32 VideoEditor3gpReader_GetMpegLengthFromStream(void* pContext){
350    M4OSA_UInt32 length=0;
351    M4OSA_UInt32 numBytes=0;
352    M4OSA_UInt32 b=0;
353
354    M4OSA_DEBUG_IF1((M4OSA_NULL==pContext), 0, "invalid context pointer");
355
356    /* the length is encoded as a sequence of bytes. The highest bit is used
357    to indicate that the length continues on the next byte.
358
359    The length can be: 0x80 0x80 0x80 0x22
360    of just            0x22 (highest bit not set)
361    */
362
363    do {
364        b=VideoEditor3gpReader_BitStreamParserShowBits(pContext, 8);
365        VideoEditor3gpReader_BitStreamParserFlushBits(pContext, 8);
366        length=(length << 7) | (b & 0x7f);
367        numBytes++;
368    } while ((b & 0x80) && numBytes < 4);
369
370    return length;
371}
372#endif /* VIDEOEDITOR_BITSTREAM_PARSER */
373/**
374************************************************************************
375* @brief    create an instance of the 3gp reader
376 * @note    allocates the context
377 *
378 * @param   pContext:       (OUT)   pointer on a reader context
379 *
380 * @return  M4NO_ERROR              there is no error
381 * @return  M4ERR_ALLOC             a memory allocation has failed
382 * @return  M4ERR_PARAMETER         at least one parameter is not valid
383************************************************************************
384*/
385
386M4OSA_ERR VideoEditor3gpReader_create(M4OSA_Context *pContext) {
387    VideoEditor3gpReader_Context* pC = NULL;
388    M4OSA_ERR err = M4NO_ERROR;
389    VIDEOEDITOR_CHECK(M4OSA_NULL != pContext , M4ERR_PARAMETER);
390
391    LOGV("VideoEditor3gpReader_create begin");
392
393    /* Context allocation & initialization */
394    SAFE_MALLOC(pC, VideoEditor3gpReader_Context, 1, "VideoEditor3gpReader");
395
396    memset(pC, sizeof(VideoEditor3gpReader_Context), 0);
397
398    pC->mAudioStreamHandler  = M4OSA_NULL;
399    pC->mAudioAu.dataAddress = M4OSA_NULL;
400    pC->mVideoStreamHandler  = M4OSA_NULL;
401    pC->mVideoAu.dataAddress = M4OSA_NULL;
402
403    pC->mAudioSeeking = M4OSA_FALSE;
404    pC->mAudioSeekTime = 0;
405
406    pC->mVideoSeeking = M4OSA_FALSE;
407    pC->mVideoSeekTime = 0;
408
409    pC->mMaxDuration = 0;
410
411    *pContext=pC;
412
413cleanUp:
414    if ( M4NO_ERROR == err ) {
415        LOGV("VideoEditor3gpReader_create no error");
416    } else {
417        LOGV("VideoEditor3gpReader_create ERROR 0x%X", err);
418    }
419    LOGV("VideoEditor3gpReader_create end ");
420    return err;
421}
422
423/**
424**************************************************************************
425* @brief    destroy the instance of the 3gp reader
426* @note after this call the context is invalid
427* @param    context:        (IN)    Context of the reader
428* @return   M4NO_ERROR              there is no error
429* @return   M4ERR_PARAMETER         pContext parameter is not properly set
430**************************************************************************
431*/
432
433M4OSA_ERR VideoEditor3gpReader_destroy(M4OSA_Context pContext) {
434    M4OSA_ERR err = M4NO_ERROR;
435    VideoEditor3gpReader_Context* pC = M4OSA_NULL;
436
437    LOGV("VideoEditor3gpReader_destroy begin");
438
439    VIDEOEDITOR_CHECK(M4OSA_NULL != pContext, M4ERR_PARAMETER);
440    pC = (VideoEditor3gpReader_Context*)pContext;
441
442    SAFE_FREE(pC->mAudioAu.dataAddress);
443    pC->mAudioAu.dataAddress = M4OSA_NULL;
444    SAFE_FREE(pC->mVideoAu.dataAddress);
445    pC->mVideoAu.dataAddress = M4OSA_NULL;
446    SAFE_FREE(pC);
447    pContext = M4OSA_NULL;
448
449cleanUp:
450    if( M4NO_ERROR == err ) {
451        LOGV("VideoEditor3gpReader_destroy no error");
452    }
453    else
454    {
455        LOGV("VideoEditor3gpReader_destroy ERROR 0x%X", err);
456    }
457
458    LOGV("VideoEditor3gpReader_destroy end ");
459    return err;
460}
461
462/**
463************************************************************************
464* @brief    open the reader and initializes its created instance
465* @note     this function open the media file
466* @param    context:            (IN)    Context of the reader
467* @param    pFileDescriptor:    (IN)    Pointer to proprietary data identifying
468*                                       the media to open
469* @return   M4NO_ERROR                  there is no error
470* @return   M4ERR_PARAMETER             the context is NULL
471* @return   M4ERR_UNSUPPORTED_MEDIA_TYPE
472*                                       the media is DRM protected
473************************************************************************
474*/
475
476M4OSA_ERR VideoEditor3gpReader_open(M4OSA_Context pContext,
477        M4OSA_Void* pFileDescriptor) {
478    VideoEditor3gpReader_Context* pC = (VideoEditor3gpReader_Context*)pContext;
479    M4OSA_ERR err = M4NO_ERROR;
480
481    LOGV("VideoEditor3gpReader_open start ");
482    M4OSA_DEBUG_IF1((M4OSA_NULL == pC),  M4ERR_PARAMETER,
483        "VideoEditor3gpReader_open: invalid context pointer");
484    M4OSA_DEBUG_IF1((M4OSA_NULL == pFileDescriptor), M4ERR_PARAMETER,
485        "VideoEditor3gpReader_open: invalid pointer pFileDescriptor");
486
487    LOGV("VideoEditor3gpReader_open Datasource start %s",
488        (char*)pFileDescriptor);
489    //pC->mDataSource = DataSource::CreateFromURI((char*)pFileDescriptor);
490    pC->mDataSource = new FileSource ((char*)pFileDescriptor);
491
492    if (pC->mDataSource == NULL) {
493        LOGV("VideoEditor3gpReader_open Datasource error");
494        return M4ERR_PARAMETER;
495    }
496
497    pC->mExtractor = MediaExtractor::Create(pC->mDataSource,
498        MEDIA_MIMETYPE_CONTAINER_MPEG4);
499
500    if (pC->mExtractor == NULL) {
501        LOGV("VideoEditor3gpReader_open extractor error");
502        return M4ERR_PARAMETER;
503    }
504
505    int32_t isDRMProtected = 0;
506    sp<MetaData> meta = pC->mExtractor->getMetaData();
507    meta->findInt32(kKeyIsDRM, &isDRMProtected);
508    if (isDRMProtected) {
509        LOGV("VideoEditorMp3Reader_open error - DRM Protected");
510        return M4ERR_UNSUPPORTED_MEDIA_TYPE;
511    }
512
513    LOGV("VideoEditor3gpReader_open end ");
514    return err;
515}
516
517/**
518************************************************************************
519* @brief    close the reader
520* @note     close the 3GP file
521* @param    context:        (IN)    Context of the reader
522* @return   M4NO_ERROR              there is no error
523* @return   M4ERR_PARAMETER         the context is NULL
524* @return   M4ERR_BAD_CONTEXT       provided context is not a valid one
525************************************************************************
526*/
527M4OSA_ERR VideoEditor3gpReader_close(M4OSA_Context context) {
528    VideoEditor3gpReader_Context *pC = (VideoEditor3gpReader_Context*)context;
529    M4READER_AudioSbrUserdata *pAudioSbrUserData;
530    M4_AccessUnit *pAU;
531    M4OSA_ERR err = M4NO_ERROR;
532
533    LOGV("VideoEditor3gpReader_close begin");
534
535    M4OSA_DEBUG_IF1((M4OSA_NULL == pC), M4ERR_PARAMETER,
536        "VideoEditor3gpReader_close: invalid context pointer");
537
538    if (pC->mAudioStreamHandler) {
539        LOGV("VideoEditor3gpReader_close Audio");
540
541        if (M4OSA_NULL != pC->mAudioStreamHandler->m_pDecoderSpecificInfo) {
542            free(pC->mAudioStreamHandler->\
543                m_pDecoderSpecificInfo);
544            pC->mAudioStreamHandler->m_decoderSpecificInfoSize = 0;
545            pC->mAudioStreamHandler->m_pDecoderSpecificInfo = M4OSA_NULL;
546        }
547
548        if ((M4DA_StreamTypeAudioAac == pC->mAudioStreamHandler->m_streamType)
549            && (M4OSA_NULL != pC->mAudioStreamHandler->m_pUserData)) {
550            pAudioSbrUserData = (M4READER_AudioSbrUserdata*)(\
551                pC->mAudioStreamHandler->m_pUserData);
552
553            pAU = (M4_AccessUnit*)pAudioSbrUserData->m_pFirstAU;
554            if (M4OSA_NULL != pAU) {
555                free(pAU);
556            }
557
558            if (M4OSA_NULL != pAudioSbrUserData->m_pAacDecoderUserConfig) {
559                free(pAudioSbrUserData->\
560                    m_pAacDecoderUserConfig);
561            }
562            free(pAudioSbrUserData);
563            pC->mAudioStreamHandler->m_pUserData = M4OSA_NULL;
564        }
565
566        if (pC->mAudioStreamHandler->m_pESDSInfo != M4OSA_NULL) {
567            free(pC->mAudioStreamHandler->m_pESDSInfo);
568            pC->mAudioStreamHandler->m_pESDSInfo = M4OSA_NULL;
569            pC->mAudioStreamHandler->m_ESDSInfoSize = 0;
570        }
571        /* Finally destroy the stream handler */
572        free(pC->mAudioStreamHandler);
573        pC->mAudioStreamHandler = M4OSA_NULL;
574
575        pC->mAudioSource->stop();
576        pC->mAudioSource.clear();
577    }
578    if (pC->mVideoStreamHandler) {
579        LOGV("VideoEditor3gpReader_close Video ");
580
581        if(M4OSA_NULL != pC->mVideoStreamHandler->m_pDecoderSpecificInfo) {
582            free(pC->mVideoStreamHandler->\
583                m_pDecoderSpecificInfo);
584            pC->mVideoStreamHandler->m_decoderSpecificInfoSize = 0;
585            pC->mVideoStreamHandler->m_pDecoderSpecificInfo = M4OSA_NULL;
586        }
587
588        if(M4OSA_NULL != pC->mVideoStreamHandler->m_pH264DecoderSpecificInfo) {
589            free(pC->mVideoStreamHandler->\
590                m_pH264DecoderSpecificInfo);
591            pC->mVideoStreamHandler->m_H264decoderSpecificInfoSize = 0;
592            pC->mVideoStreamHandler->m_pH264DecoderSpecificInfo = M4OSA_NULL;
593        }
594
595        if(pC->mVideoStreamHandler->m_pESDSInfo != M4OSA_NULL) {
596            free(pC->mVideoStreamHandler->m_pESDSInfo);
597            pC->mVideoStreamHandler->m_pESDSInfo = M4OSA_NULL;
598            pC->mVideoStreamHandler->m_ESDSInfoSize = 0;
599        }
600
601        /* Finally destroy the stream handler */
602        free(pC->mVideoStreamHandler);
603        pC->mVideoStreamHandler = M4OSA_NULL;
604
605        pC->mVideoSource->stop();
606        pC->mVideoSource.clear();
607    }
608    pC->mExtractor.clear();
609    pC->mDataSource.clear();
610
611    LOGV("VideoEditor3gpReader_close end");
612    return err;
613}
614
615/**
616************************************************************************
617* @brief    get an option from the 3gp reader
618* @note     it allows the caller to retrieve a property value:
619*
620* @param    context:        (IN)    Context of the reader
621* @param    optionId:       (IN)    indicates the option to get
622* @param    pValue:         (OUT)   pointer to structure or value (allocated
623*                                   by user) where option is stored
624*
625* @return   M4NO_ERROR              there is no error
626* @return   M4ERR_BAD_CONTEXT       provided context is not a valid one
627* @return   M4ERR_PARAMETER         at least one parameter is not properly set
628* @return   M4ERR_BAD_OPTION_ID     when the option ID is not a valid one
629* @return   M4ERR_VIDEO_NOT_H263    No video stream H263 in file.
630* @return   M4ERR_NO_VIDEO_STREAM_RETRIEVED_YET
631*           Function 3gpReader_getNextStreamHandler must be called before
632************************************************************************
633*/
634M4OSA_ERR VideoEditor3gpReader_getOption(M4OSA_Context context,
635        M4OSA_OptionID optionId, M4OSA_DataOption pValue) {
636    VideoEditor3gpReader_Context* pC = (VideoEditor3gpReader_Context*)context;
637    M4OSA_ERR err = M4NO_ERROR;
638
639    LOGV("VideoEditor3gpReader_getOption begin %d", optionId);
640
641    M4OSA_DEBUG_IF1((M4OSA_NULL == pC), M4ERR_PARAMETER,
642        "invalid context pointer");
643    M4OSA_DEBUG_IF1((M4OSA_NULL == pValue), M4ERR_PARAMETER,
644        "VideoEditor3gpReader_getOption: invalid pointer on value");
645
646    switch (optionId) {
647    case M4READER_kOptionID_Duration:
648        {
649            LOGV("VideoEditor3gpReader_getOption duration %d",pC->mMaxDuration);
650            *(M4OSA_Time*)pValue = pC->mMaxDuration;
651        }
652        break;
653    case M4READER_kOptionID_Version:
654        /* not used */
655        LOGV("VideoEditor3gpReader_getOption: M4READER_kOptionID_Version");
656        break;
657
658    case M4READER_kOptionID_Copyright:
659        /* not used */
660        LOGV(">>>>>>>   M4READER_kOptionID_Copyright");
661        break;
662
663    case M4READER_kOptionID_CreationTime:
664        /* not used */
665        LOGV("VideoEditor3gpReader_getOption M4READER_kOptionID_CreationTime");
666    break;
667
668    case M4READER_kOptionID_Bitrate:
669        {
670            M4OSA_UInt32* pBitrate = (M4OSA_UInt32*)pValue;
671
672            if (pC->mMaxDuration != 0) {
673                M4OSA_UInt32 ui32Tmp = (M4OSA_UInt32)pC->mMaxDuration;
674                *pBitrate = (M4OSA_UInt32)((M4OSA_Double)pC->mFileSize * \
675                    8000.0 / (M4OSA_Double)ui32Tmp);
676                LOGV("3gpReader_getOption bitrate:  %d", *pBitrate);
677            }
678            *pBitrate = 384000; //check
679            LOGV("VideoEditor3gpReader_getOption bitrate %ld", *pBitrate);
680        }
681    break;
682    case M4READER_3GP_kOptionID_H263Properties:
683        {
684            if(M4OSA_NULL == pC->mVideoStreamHandler) {
685                LOGV("VideoEditor3gpReader_getOption no videoStream retrieved");
686
687                err = M4ERR_NO_VIDEO_STREAM_RETRIEVED_YET;
688                break;
689            }
690            if((M4DA_StreamTypeVideoH263 != pC->mVideoStreamHandler->\
691                m_streamType) || (pC->mVideoStreamHandler->\
692                m_decoderSpecificInfoSize < 7)) {
693                LOGV("VideoEditor3gpReader_getOption DSI Size %d",
694                    pC->mVideoStreamHandler->m_decoderSpecificInfoSize);
695
696                err = M4ERR_VIDEO_NOT_H263;
697                break;
698            }
699
700            /* MAGICAL in the decoder confi H263: the 7th byte is the profile
701             * number, 6th byte is the level number */
702            ((M4READER_3GP_H263Properties *)pValue)->uiProfile =
703                pC->mVideoStreamHandler->m_pDecoderSpecificInfo[6];
704            ((M4READER_3GP_H263Properties *)pValue)->uiLevel =
705                pC->mVideoStreamHandler->m_pDecoderSpecificInfo[5];
706            LOGV("VideoEditor3gpReader_getOption M4READER_3GP_kOptionID_\
707            H263Properties end");
708        }
709        break;
710    case M4READER_3GP_kOptionID_PurpleLabsDrm:
711        LOGV("VideoEditor3gpReaderOption M4READER_3GP_kOptionID_PurpleLabsDrm");
712        /* not used */
713        break;
714
715    case M4READER_kOptionID_GetNumberOfAudioAu:
716        /* not used */
717        LOGV("VideoEditor3gpReadeOption M4READER_kOptionID_GetNumberOfAudioAu");
718    break;
719
720    case M4READER_kOptionID_GetNumberOfVideoAu:
721        /* not used */
722        LOGV("VideoEditor3gpReader_getOption :GetNumberOfVideoAu");
723    break;
724
725    case M4READER_kOptionID_GetMetadata:
726        /* not used */
727        LOGV("VideoEditor3gpReader_getOption M4READER_kOptionID_GetMetadata");
728    break;
729
730    case M4READER_kOptionID_3gpFtypBox:
731        /* used only for SEMC */
732        LOGV("VideoEditor3gpReader_getOption M4READER_kOptionID_3gpFtypBox");
733        err = M4ERR_BAD_OPTION_ID; //check this
734        break;
735
736#ifdef OPTIONID_GET_NEXT_VIDEO_CTS
737    case M4READER_3GP_kOptionID_getNextVideoCTS:
738        /* not used */
739        LOGV("VideoEditor3gpReader_getOption: getNextVideoCTS");
740        break;
741#endif
742    default:
743        {
744            err = M4ERR_BAD_OPTION_ID;
745            LOGV("VideoEditor3gpReader_getOption M4ERR_BAD_OPTION_ID");
746        }
747        break;
748    }
749    LOGV("VideoEditor3gpReader_getOption end: optionID: x%x", optionId);
750    return err;
751}
752/**
753************************************************************************
754* @brief    set an option on the 3gp reader
755* @note No option can be set yet.
756* @param    context:        (IN)    Context of the reader
757* @param    optionId:       (IN)    indicates the option to set
758* @param    pValue:         (IN)    pointer to structure or value (allocated
759*                                   by user) where option is stored
760* @return   M4NO_ERROR              there is no error
761* @return   M4ERR_BAD_CONTEXT       provided context is not a valid one
762* @return   M4ERR_PARAMETER         at least one parameter is not properly set
763* @return   M4ERR_BAD_OPTION_ID     when the option ID is not a valid one
764************************************************************************
765*/
766M4OSA_ERR VideoEditor3gpReader_setOption(M4OSA_Context context,
767        M4OSA_OptionID optionId, M4OSA_DataOption pValue) {
768    VideoEditor3gpReader_Context* pC = (VideoEditor3gpReader_Context*)context;
769    M4OSA_ERR err = M4NO_ERROR;
770
771    /* Check function parameters */
772    M4OSA_DEBUG_IF1((M4OSA_NULL == pC), M4ERR_PARAMETER,
773        "invalid context pointer");
774    M4OSA_DEBUG_IF1((M4OSA_NULL == pValue), M4ERR_PARAMETER,
775        "invalid value pointer");
776
777    LOGV("VideoEditor3gpReader_setOption begin %d",optionId);
778
779    switch(optionId) {
780        case M4READER_kOptionID_SetOsaFileReaderFctsPtr:
781        break;
782
783        case M4READER_3GP_kOptionID_AudioOnly:
784        break;
785
786        case M4READER_3GP_kOptionID_VideoOnly:
787        break;
788
789        case M4READER_3GP_kOptionID_FastOpenMode:
790        break;
791
792        case M4READER_kOptionID_MaxMetadataSize:
793        break;
794
795        default:
796        {
797            LOGV("VideoEditor3gpReader_setOption: returns M4ERR_BAD_OPTION_ID");
798            err = M4ERR_BAD_OPTION_ID;
799        }
800        break;
801    }
802    LOGV("VideoEditor3gpReader_setOption end ");
803    return err;
804}
805/**
806 ************************************************************************
807 * @brief   fill the access unit structure with initialization values
808 * @param   context:        (IN)     Context of the reader
809 * @param   pStreamHandler: (IN)     pointer to the stream handler to which
810 *                                   the access unit will be associated
811 * @param   pAccessUnit:    (IN/OUT) pointer to the access unit (allocated
812 *                                   by the caller) to initialize
813 * @return  M4NO_ERROR               there is no error
814 * @return  M4ERR_PARAMETER          at least one parameter is not properly set
815 ************************************************************************
816*/
817M4OSA_ERR VideoEditor3gpReader_fillAuStruct(M4OSA_Context context,
818        M4_StreamHandler *pStreamHandler, M4_AccessUnit *pAccessUnit) {
819    VideoEditor3gpReader_Context* pC = (VideoEditor3gpReader_Context*)context;
820    M4OSA_ERR err= M4NO_ERROR;
821
822    M4OSA_DEBUG_IF1((pC == 0),             M4ERR_PARAMETER,
823        "VideoEditor3gpReader_fillAuStruct: invalid context");
824    M4OSA_DEBUG_IF1((pStreamHandler == 0), M4ERR_PARAMETER,
825        "VideoEditor3gpReader_fillAuStruc invalid pointer to M4_StreamHandler");
826    M4OSA_DEBUG_IF1((pAccessUnit == 0),    M4ERR_PARAMETER,
827        "VideoEditor3gpReader_fillAuStruct: invalid pointer to M4_AccessUnit");
828
829    LOGV("VideoEditor3gpReader_fillAuStruct begin");
830
831    /* Initialize pAccessUnit structure */
832    pAccessUnit->m_size         = 0;
833    pAccessUnit->m_CTS          = 0;
834    pAccessUnit->m_DTS          = 0;
835    pAccessUnit->m_attribute    = 0;
836    pAccessUnit->m_dataAddress  = M4OSA_NULL;
837    pAccessUnit->m_maxsize      = pStreamHandler->m_maxAUSize;
838    pAccessUnit->m_streamID     = pStreamHandler->m_streamId;
839    pAccessUnit->m_structSize   = sizeof(M4_AccessUnit);
840
841    LOGV("VideoEditor3gpReader_fillAuStruct end");
842    return M4NO_ERROR;
843}
844
845/**
846********************************************************************************
847* @brief    jump into the stream at the specified time
848* @note
849* @param    context:        (IN)   Context of the reader
850* @param    pStreamHandler  (IN)   the stream handler of the stream to make jump
851* @param    pTime           (I/O)IN  the time to jump to (in ms)
852*                                OUT the time to which the stream really jumped
853* @return   M4NO_ERROR             there is no error
854* @return   M4ERR_PARAMETER        at least one parameter is not properly set
855********************************************************************************
856*/
857M4OSA_ERR VideoEditor3gpReader_jump(M4OSA_Context context,
858        M4_StreamHandler *pStreamHandler, M4OSA_Int32* pTime) {
859    VideoEditor3gpReader_Context* pC = (VideoEditor3gpReader_Context*)context;
860    M4OSA_ERR err = M4NO_ERROR;
861    M4SYS_AccessUnit* pAu;
862    M4OSA_Time time64;
863
864    M4OSA_DEBUG_IF1((pC == 0), M4ERR_PARAMETER,
865        "VideoEditor3gpReader_jump: invalid context");
866    M4OSA_DEBUG_IF1((pStreamHandler == 0), M4ERR_PARAMETER,
867        "VideoEditor3gpReader_jump: invalid pointer to M4_StreamHandler");
868    M4OSA_DEBUG_IF1((pTime == 0), M4ERR_PARAMETER,
869        "VideoEditor3gpReader_jump: invalid time pointer");
870
871    LOGV("VideoEditor3gpReader_jump begin");
872
873    if (*pTime == (pStreamHandler->m_duration)) {
874        *pTime -= 1;
875    }
876    time64 = (M4OSA_Time)*pTime;
877
878    LOGV("VideoEditor3gpReader_jump time us %ld ", time64);
879
880    if ((pC->mAudioStreamHandler != M4OSA_NULL) &&
881            (pStreamHandler->m_streamId == pC->mAudioStreamHandler->m_streamId))
882            {
883        pAu = &pC->mAudioAu;
884        pAu->CTS = time64;
885        pAu->DTS = time64;
886
887        time64 = time64 * 1000; /* Convert the time into micro sec */
888        pC->mAudioSeeking = M4OSA_TRUE;
889        pC->mAudioSeekTime = time64;
890        LOGV("VideoEditor3gpReader_jump AUDIO time us %ld ", time64);
891    } else if ((pC->mVideoStreamHandler != M4OSA_NULL) &&
892            (pStreamHandler->m_streamId == pC->mVideoStreamHandler->m_streamId))
893            {
894        pAu = &pC->mVideoAu;
895        pAu->CTS = time64;
896        pAu->DTS = time64;
897
898        time64 = time64 * 1000; /* Convert the time into micro sec */
899        pC->mVideoSeeking = M4OSA_TRUE;
900        pC->mVideoSeekTime = time64;
901        LOGV("VideoEditor3gpReader_jump VIDEO time us %ld ", time64);
902    } else {
903        LOGV("VideoEditor3gpReader_jump passed StreamHandler is not known\n");
904        return M4ERR_PARAMETER;
905    }
906    time64 = time64 / 1000; /* Convert the time into milli sec */
907    LOGV("VideoEditor3gpReader_jump time ms before seekset %ld ", time64);
908
909    *pTime = (M4OSA_Int32)time64;
910
911    LOGV("VideoEditor3gpReader_jump end");
912    err = M4NO_ERROR;
913    return err;
914}
915/**
916********************************************************************************
917* @brief    reset the stream, that is seek it to beginning and make it ready
918* @note
919* @param    context:        (IN)    Context of the reader
920* @param    pStreamHandler  (IN)    The stream handler of the stream to reset
921* @return   M4NO_ERROR              there is no error
922* @return   M4ERR_PARAMETER         at least one parameter is not properly set
923********************************************************************************
924*/
925M4OSA_ERR VideoEditor3gpReader_reset(M4OSA_Context context,
926        M4_StreamHandler *pStreamHandler) {
927    VideoEditor3gpReader_Context* pC = (VideoEditor3gpReader_Context*)context;
928    M4OSA_ERR err = M4NO_ERROR;
929    M4SYS_StreamID streamIdArray[2];
930    M4SYS_AccessUnit* pAu;
931    M4OSA_Time time64 = 0;
932
933    M4OSA_DEBUG_IF1((pC == 0), M4ERR_PARAMETER,
934        "VideoEditor3gpReader_reset: invalid context");
935    M4OSA_DEBUG_IF1((pStreamHandler == 0), M4ERR_PARAMETER,
936        "VideoEditor3gpReader_reset: invalid pointer to M4_StreamHandler");
937
938    LOGV("VideoEditor3gpReader_reset begin");
939
940    if (pStreamHandler == (M4_StreamHandler*)pC->mAudioStreamHandler) {
941        pAu = &pC->mAudioAu;
942    } else if (pStreamHandler == (M4_StreamHandler*)pC->mVideoStreamHandler) {
943        pAu = &pC->mVideoAu;
944    } else {
945        LOGV("VideoEditor3gpReader_reset passed StreamHandler is not known\n");
946        return M4ERR_PARAMETER;
947    }
948
949    pAu->CTS = time64;
950    pAu->DTS = time64;
951
952    LOGV("VideoEditor3gpReader_reset end");
953    return err;
954}
955
956/**
957********************************************************************************
958* @brief  Gets an access unit (AU) from the stream handler source.
959* @note   An AU is the smallest possible amount of data to be decoded by decoder
960*
961* @param    context:        (IN) Context of the reader
962* @param    pStreamHandler  (IN) The stream handler of the stream to make jump
963* @param    pAccessUnit     (IO) Pointer to access unit to fill with read data
964* @return   M4NO_ERROR           there is no error
965* @return   M4ERR_PARAMETER      at least one parameter is not properly set
966* @returns  M4ERR_ALLOC          memory allocation failed
967* @returns  M4WAR_NO_MORE_AU     there are no more access unit in the stream
968********************************************************************************
969*/
970M4OSA_ERR VideoEditor3gpReader_getNextAu(M4OSA_Context context,
971        M4_StreamHandler *pStreamHandler, M4_AccessUnit *pAccessUnit) {
972    VideoEditor3gpReader_Context* pC=(VideoEditor3gpReader_Context*)context;
973    M4OSA_ERR err = M4NO_ERROR;
974    M4SYS_AccessUnit* pAu;
975    int64_t tempTime64 = 0;
976    MediaBuffer *mMediaBuffer = NULL;
977    MediaSource::ReadOptions options;
978    M4OSA_Bool flag = M4OSA_FALSE;
979    status_t error;
980    int32_t i32Tmp = 0;
981
982    M4OSA_DEBUG_IF1((pReaderContext == 0), M4ERR_PARAMETER,
983        "VideoEditor3gpReader_getNextAu: invalid context");
984    M4OSA_DEBUG_IF1((pStreamHandler == 0), M4ERR_PARAMETER,
985        "VideoEditor3gpReader_getNextAu: invalid pointer to M4_StreamHandler");
986    M4OSA_DEBUG_IF1((pAccessUnit == 0),    M4ERR_PARAMETER,
987        "VideoEditor3gpReader_getNextAu: invalid pointer to M4_AccessUnit");
988
989    LOGV("VideoEditor3gpReader_getNextAu begin");
990
991    if (pStreamHandler == (M4_StreamHandler*)pC->mAudioStreamHandler) {
992        LOGV("VideoEditor3gpReader_getNextAu audio stream");
993        pAu = &pC->mAudioAu;
994        if (pC->mAudioSeeking == M4OSA_TRUE) {
995            LOGV("VideoEditor3gpReader_getNextAu audio seek time: %ld",
996                pC->mAudioSeekTime);
997            options.setSeekTo(pC->mAudioSeekTime);
998            pC->mAudioSource->read(&mMediaBuffer, &options);
999
1000            mMediaBuffer->meta_data()->findInt64(kKeyTime,
1001                (int64_t*)&tempTime64);
1002            options.clearSeekTo();
1003            pC->mAudioSeeking = M4OSA_FALSE;
1004            flag = M4OSA_TRUE;
1005        } else {
1006            LOGV("VideoEditor3gpReader_getNextAu audio no seek:");
1007            pC->mAudioSource->read(&mMediaBuffer, &options);
1008            if (mMediaBuffer != NULL) {
1009                mMediaBuffer->meta_data()->findInt64(kKeyTime,
1010                    (int64_t*)&tempTime64);
1011            }
1012        }
1013    } else if (pStreamHandler == (M4_StreamHandler*)pC->mVideoStreamHandler) {
1014        LOGV("VideoEditor3gpReader_getNextAu video steram ");
1015        pAu = &pC->mVideoAu;
1016        if(pC->mVideoSeeking == M4OSA_TRUE) {
1017            flag = M4OSA_TRUE;
1018            LOGV("VideoEditor3gpReader_getNextAu seek: %ld",pC->mVideoSeekTime);
1019            options.setSeekTo(pC->mVideoSeekTime,
1020                MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC);
1021            do
1022            {
1023                if (mMediaBuffer != NULL) {
1024                    LOGV("VideoEditor3gpReader_getNextAu free the MediaBuffer");
1025                    mMediaBuffer->release();
1026                }
1027                error = pC->mVideoSource->read(&mMediaBuffer, &options);
1028                LOGV("VE3gpReader_getNextAu MediaBuffer %x , error %d",
1029                    mMediaBuffer, error);
1030                if (mMediaBuffer != NULL)
1031                {
1032                    if (mMediaBuffer->meta_data()->findInt32(kKeyIsSyncFrame,
1033                        &i32Tmp) && i32Tmp) {
1034                            LOGV("SYNC FRAME FOUND--%d", i32Tmp);
1035                        pAu->attribute = AU_RAP;
1036                    }
1037                    else {
1038                        pAu->attribute = AU_P_Frame;
1039                    }
1040                    mMediaBuffer->meta_data()->findInt64(kKeyTime,
1041                        (int64_t*)&tempTime64);
1042                } else {
1043                    break;
1044                }
1045                options.clearSeekTo();
1046            } while(tempTime64 < pC->mVideoSeekTime);
1047
1048            LOGV("VE3gpReader_getNextAu: video  time with seek  = %lld:",
1049                tempTime64);
1050            pC->mVideoSeeking = M4OSA_FALSE;
1051        } else {
1052            LOGV("VideoEditor3gpReader_getNextAu video no seek:");
1053            pC->mVideoSource->read(&mMediaBuffer, &options);
1054
1055            if(mMediaBuffer != NULL) {
1056                if (mMediaBuffer->meta_data()->findInt32(kKeyIsSyncFrame,
1057                    &i32Tmp) && i32Tmp) {
1058                    LOGV("SYNC FRAME FOUND--%d", i32Tmp);
1059                    pAu->attribute = AU_RAP;
1060                }
1061                else {
1062                    pAu->attribute = AU_P_Frame;
1063                }
1064                mMediaBuffer->meta_data()->findInt64(kKeyTime,
1065                    (int64_t*)&tempTime64);
1066                LOGV("VE3gpReader_getNextAu: video no seek time = %lld:",
1067                    tempTime64);
1068            }else {
1069                LOGV("VE3gpReader_getNextAu:video no seek time buffer is NULL");
1070            }
1071        }
1072    } else {
1073        LOGV("VideoEditor3gpReader_getNextAu M4ERR_PARAMETER");
1074        return M4ERR_PARAMETER;
1075    }
1076
1077    if (mMediaBuffer != NULL) {
1078        if( (pAu->dataAddress == NULL) ||  (pAu->size < \
1079            mMediaBuffer->range_length())) {
1080            if(pAu->dataAddress != NULL) {
1081                free((M4OSA_Int32*)pAu->dataAddress);
1082                pAu->dataAddress = NULL;
1083            }
1084            LOGV("Buffer lenght = %d ,%d",(mMediaBuffer->range_length() +\
1085                3) & ~0x3,(mMediaBuffer->range_length()));
1086
1087            pAu->dataAddress = (M4OSA_Int32*)M4OSA_32bitAlignedMalloc(
1088                (mMediaBuffer->range_length() + 3) & ~0x3,M4READER_3GP,
1089                    (M4OSA_Char*)"pAccessUnit->m_dataAddress" );
1090            if(pAu->dataAddress == NULL) {
1091                LOGV("VideoEditor3gpReader_getNextAu malloc failed");
1092                return M4ERR_ALLOC;
1093            }
1094        }
1095        pAu->size = mMediaBuffer->range_length();
1096
1097        memcpy((void *)pAu->dataAddress,
1098            (void *)((const char *)mMediaBuffer->data() + mMediaBuffer->range_offset()),
1099            mMediaBuffer->range_length());
1100
1101        if( (pStreamHandler == (M4_StreamHandler*)pC->mVideoStreamHandler)  &&
1102            (pStreamHandler->m_streamType == M4DA_StreamTypeVideoMpeg4Avc) ) {
1103            M4OSA_UInt32 size = mMediaBuffer->range_length();
1104            M4OSA_UInt8 *lbuffer;
1105
1106            lbuffer = (M4OSA_UInt8 *) pAu->dataAddress;
1107            LOGV("pAccessUnit->m_dataAddress size = %x",size);
1108
1109            lbuffer[0] = (size >> 24) & 0xFF;
1110            lbuffer[1] = (size >> 16) & 0xFF;
1111            lbuffer[2] = (size >> 8) & 0xFF;
1112            lbuffer[3] = (size) & 0xFF;
1113        }
1114
1115        pAu->CTS = tempTime64;
1116
1117        pAu->CTS = pAu->CTS / 1000; //converting the microsec to millisec
1118        LOGV("VideoEditor3gpReader_getNextAu CTS = %ld",pAu->CTS);
1119
1120        pAu->DTS  = pAu->CTS;
1121        if (pStreamHandler == (M4_StreamHandler*)pC->mAudioStreamHandler) {
1122            pAu->attribute = M4SYS_kFragAttrOk;
1123        }
1124        mMediaBuffer->release();
1125
1126        pAccessUnit->m_dataAddress = (M4OSA_Int8*) pAu->dataAddress;
1127        pAccessUnit->m_size = pAu->size;
1128        pAccessUnit->m_maxsize = pAu->size;
1129        pAccessUnit->m_CTS = pAu->CTS;
1130        pAccessUnit->m_DTS = pAu->DTS;
1131        pAccessUnit->m_attribute = pAu->attribute;
1132
1133    } else {
1134        LOGV("VideoEditor3gpReader_getNextAu: M4WAR_NO_MORE_AU (EOS) reached");
1135        pAccessUnit->m_size = 0;
1136        err = M4WAR_NO_MORE_AU;
1137    }
1138    options.clearSeekTo();
1139
1140    pAu->nbFrag = 0;
1141    mMediaBuffer = NULL;
1142    LOGV("VideoEditor3gpReader_getNextAu end ");
1143
1144    return err;
1145}
1146/**
1147 *******************************************************************************
1148 * @brief   Split the AVC DSI in its different components and write it in
1149 *          ONE memory buffer
1150 * @note
1151 * @param   pStreamHandler:         (IN/OUT) The MPEG4-AVC stream
1152 * @param   pDecoderConfigLocal:    (IN) The DSI buffer
1153 * @param   decoderConfigSizeLocal: (IN) The DSI buffer size
1154 * @return  M4NO_ERROR              there is no error
1155 * @return  ERR_FILE_SYNTAX_ERROR   pDecoderConfigLocal is NULL
1156 *******************************************************************************
1157*/
1158static M4OSA_ERR VideoEditor3gpReader_AnalyseAvcDsi(
1159        M4_StreamHandler *pStreamHandler, M4OSA_Int32* pDecoderConfigLocal,
1160        M4OSA_Int32 decoderConfigSizeLocal) {
1161    struct _avcSpecificInfo *pAvcSpecInfo = M4OSA_NULL;
1162    M4OSA_UInt32 uiSpecInfoSize;
1163    M4OSA_Context pBitParserContext = M4OSA_NULL;
1164    M4OSA_MemAddr8 pPos;
1165
1166    /**
1167     * First parsing to get the total allocation size (we must not do
1168     * multiple malloc, but only one instead) */
1169    {
1170        M4OSA_Int32 val;
1171        M4OSA_UInt32 i,j;
1172        M4OSA_UInt8 nalUnitLength;
1173        M4OSA_UInt8  numOfSequenceParameterSets;
1174        M4OSA_UInt32 uiTotalSizeOfSPS = 0;
1175        M4OSA_UInt8  numOfPictureParameterSets;
1176        M4OSA_UInt32 uiTotalSizeOfPPS = 0;
1177        M4OSA_UInt32 uiSize;
1178        struct _avcSpecificInfo avcSpIf;
1179
1180        avcSpIf.m_nalUnitLength = 0;
1181
1182        if (M4OSA_NULL == pDecoderConfigLocal) {
1183            return M4ERR_READER3GP_DECODER_CONFIG_ERROR;
1184        }
1185
1186        VideoEditor3gpReader_MPEG4BitStreamParserInit(&pBitParserContext,
1187            pDecoderConfigLocal, decoderConfigSizeLocal);
1188
1189        if (M4OSA_NULL == pBitParserContext) {
1190            return M4ERR_ALLOC;
1191        }
1192
1193        VideoEditor3gpReader_BitStreamParserFlushBits(pBitParserContext, 8);
1194                                       /* 8 bits -- configuration version */
1195        VideoEditor3gpReader_BitStreamParserFlushBits(pBitParserContext, 8);
1196                                       /* 8 bits -- avc profile indication*/
1197        VideoEditor3gpReader_BitStreamParserFlushBits(pBitParserContext, 8);
1198                                       /* 8 bits -- profile compatibility */
1199        VideoEditor3gpReader_BitStreamParserFlushBits(pBitParserContext, 8);
1200                                       /* 8 bits -- avc level indication*/
1201        val=VideoEditor3gpReader_BitStreamParserShowBits(pBitParserContext, 8);
1202                       /* 6 bits reserved 111111b 2 bits length Size minus one*/
1203        VideoEditor3gpReader_BitStreamParserFlushBits(pBitParserContext, 8);
1204                                       /* m_nalUnitLength */
1205
1206        nalUnitLength = (M4OSA_UInt8)((val & 0x03) + 1);/*0b11111100*/
1207        if (nalUnitLength > 4) {
1208            pStreamHandler->m_decoderSpecificInfoSize = 0;
1209            pStreamHandler->m_pDecoderSpecificInfo = M4OSA_NULL;
1210            VideoEditor3gpReader_BitStreamParserCleanUp(pBitParserContext);
1211        } else {
1212            /**
1213             * SPS table */
1214            val=VideoEditor3gpReader_BitStreamParserShowBits(pBitParserContext,
1215            8);/* 3 bits-reserved 111b-5 bits number of sequence parameter set*/
1216            numOfSequenceParameterSets = val & 0x1F;
1217            /*1F instead of E0*/ /*0b11100000*/ /*Number of seq parameter sets*/
1218            VideoEditor3gpReader_BitStreamParserFlushBits(pBitParserContext, 8);
1219            for (i=0; i < numOfSequenceParameterSets; i++) {
1220                /**
1221                 * Get the size of this element */
1222                uiSize =
1223                    (M4OSA_UInt32)VideoEditor3gpReader_BitStreamParserShowBits(
1224                    pBitParserContext, 16);
1225                uiTotalSizeOfSPS += uiSize;
1226                VideoEditor3gpReader_BitStreamParserFlushBits(
1227                    pBitParserContext, 16);
1228                /**
1229                 *Read the element(dont keep it, we only want size right now) */
1230                for (j=0; j<uiSize; j++) {
1231                    VideoEditor3gpReader_BitStreamParserFlushBits(
1232                        pBitParserContext, 8);
1233                }
1234            }
1235
1236            /**
1237             * SPS table */
1238            numOfPictureParameterSets=(M4OSA_UInt8)\
1239                VideoEditor3gpReader_BitStreamParserShowBits(pBitParserContext,
1240                    8);
1241            VideoEditor3gpReader_BitStreamParserFlushBits(pBitParserContext, 8);
1242            for (i=0; i < numOfPictureParameterSets; i++) {
1243                /**
1244                 * Get the size of this element */
1245                uiSize = (M4OSA_UInt32)
1246                    VideoEditor3gpReader_BitStreamParserShowBits(
1247                    pBitParserContext, 16);
1248                uiTotalSizeOfPPS += uiSize;
1249                VideoEditor3gpReader_BitStreamParserFlushBits(
1250                    pBitParserContext, 16);
1251                /**
1252                 *Read the element(dont keep it,we only want size right now)*/
1253                for (j=0; j<uiSize; j++) {
1254                    VideoEditor3gpReader_BitStreamParserFlushBits(
1255                        pBitParserContext, 8);
1256                }
1257            }
1258
1259            /**
1260             * Compute the size of the full buffer */
1261            uiSpecInfoSize = sizeof(struct _avcSpecificInfo) +
1262                     numOfSequenceParameterSets * sizeof(struct _parameterSet)
1263                     + /**< size of the table of SPS elements */
1264                     numOfPictureParameterSets  * sizeof(struct _parameterSet)
1265                     + /**< size of the table of PPS elements */
1266                     uiTotalSizeOfSPS +
1267                     uiTotalSizeOfPPS;
1268            /**
1269             * Allocate the buffer */
1270            pAvcSpecInfo =(struct _avcSpecificInfo*)M4OSA_32bitAlignedMalloc(uiSpecInfoSize,
1271                M4READER_3GP, (M4OSA_Char*)"MPEG-4 AVC DecoderSpecific");
1272            if (M4OSA_NULL == pAvcSpecInfo) {
1273                VideoEditor3gpReader_BitStreamParserCleanUp(pBitParserContext);
1274                return M4ERR_ALLOC;
1275            }
1276
1277            /**
1278             * Set the pointers to the correct part of the buffer */
1279            pAvcSpecInfo->m_nalUnitLength = nalUnitLength;
1280            pAvcSpecInfo->m_numOfSequenceParameterSets =
1281                numOfSequenceParameterSets;
1282            pAvcSpecInfo->m_numOfPictureParameterSets  =
1283                numOfPictureParameterSets;
1284
1285            /* We place the SPS param sets table after m_pPictureParameterSet */
1286            pAvcSpecInfo->m_pSequenceParameterSet= (struct _parameterSet*)(
1287                (M4OSA_MemAddr8)(&pAvcSpecInfo->m_pPictureParameterSet) +
1288                sizeof(pAvcSpecInfo->m_pPictureParameterSet));
1289            /*We place the PPS param sets table after the SPS param sets table*/
1290            pAvcSpecInfo->m_pPictureParameterSet = (struct _parameterSet*)(
1291                (M4OSA_MemAddr8)(pAvcSpecInfo->m_pSequenceParameterSet) +
1292                (numOfSequenceParameterSets * sizeof(struct _parameterSet)));
1293            /**< The data will be placed after the PPS param sets table */
1294            pPos = (M4OSA_MemAddr8)pAvcSpecInfo->m_pPictureParameterSet +
1295                (numOfPictureParameterSets * sizeof(struct _parameterSet));
1296
1297            /**
1298             * reset the bit parser */
1299            VideoEditor3gpReader_BitStreamParserCleanUp(pBitParserContext);
1300        }
1301    }
1302
1303    /**
1304     * Second parsing to copy the data */
1305    if (M4OSA_NULL != pAvcSpecInfo) {
1306        M4OSA_Int32 i,j;
1307
1308        VideoEditor3gpReader_MPEG4BitStreamParserInit(&pBitParserContext,
1309            pDecoderConfigLocal, decoderConfigSizeLocal);
1310
1311        if (M4OSA_NULL == pBitParserContext) {
1312            free(pAvcSpecInfo);
1313            return M4ERR_ALLOC;
1314        }
1315
1316        VideoEditor3gpReader_BitStreamParserFlushBits(pBitParserContext, 8);
1317            /* 8 bits -- configuration version */
1318        VideoEditor3gpReader_BitStreamParserFlushBits(pBitParserContext, 8);
1319            /* 8 bits -- avc profile indication*/
1320        VideoEditor3gpReader_BitStreamParserFlushBits(pBitParserContext, 8);
1321            /* 8 bits -- profile compatibility */
1322        VideoEditor3gpReader_BitStreamParserFlushBits(pBitParserContext, 8);
1323            /* 8 bits -- avc level indication*/
1324        VideoEditor3gpReader_BitStreamParserFlushBits(pBitParserContext, 8);
1325            /* m_nalUnitLength */
1326        VideoEditor3gpReader_BitStreamParserFlushBits(pBitParserContext, 8);
1327        /* 3 bits -- reserved 111b -- 5 bits number of sequence parameter set*/
1328
1329        for (i=0; i < pAvcSpecInfo->m_numOfSequenceParameterSets; i++) {
1330            pAvcSpecInfo->m_pSequenceParameterSet[i].m_length =
1331                (M4OSA_UInt16)VideoEditor3gpReader_BitStreamParserShowBits(
1332                pBitParserContext, 16);
1333            VideoEditor3gpReader_BitStreamParserFlushBits(pBitParserContext,16);
1334
1335            pAvcSpecInfo->m_pSequenceParameterSet[i].m_pParameterSetUnit =
1336                (M4OSA_UInt8*)pPos;  /**< current position in the buffer */
1337            pPos += pAvcSpecInfo->m_pSequenceParameterSet[i].m_length;
1338                /**< increment the position in the buffer */
1339            for (j=0; j<pAvcSpecInfo->m_pSequenceParameterSet[i].m_length;j++){
1340                pAvcSpecInfo->m_pSequenceParameterSet[i].m_pParameterSetUnit[j]=
1341                    (M4OSA_UInt8)VideoEditor3gpReader_BitStreamParserShowBits(
1342                    pBitParserContext, 8);
1343                VideoEditor3gpReader_BitStreamParserFlushBits(
1344                    pBitParserContext, 8);
1345            }
1346        }
1347
1348        VideoEditor3gpReader_BitStreamParserFlushBits(pBitParserContext, 8);
1349            /* number of pîcture parameter set*/
1350
1351        for (i=0; i < pAvcSpecInfo->m_numOfPictureParameterSets; i++) {
1352            pAvcSpecInfo->m_pPictureParameterSet[i].m_length =
1353                (M4OSA_UInt16)VideoEditor3gpReader_BitStreamParserShowBits(
1354                pBitParserContext, 16);
1355            VideoEditor3gpReader_BitStreamParserFlushBits(pBitParserContext,16);
1356
1357            pAvcSpecInfo->m_pPictureParameterSet[i].m_pParameterSetUnit =
1358                (M4OSA_UInt8*)pPos;   /**< current position in the buffer */
1359            pPos += pAvcSpecInfo->m_pPictureParameterSet[i].m_length;
1360                /**< increment the position in the buffer */
1361            for (j=0; j<pAvcSpecInfo->m_pPictureParameterSet[i].m_length; j++) {
1362                pAvcSpecInfo->m_pPictureParameterSet[i].m_pParameterSetUnit[j] =
1363                    (M4OSA_UInt8)VideoEditor3gpReader_BitStreamParserShowBits(
1364                    pBitParserContext, 8);
1365                VideoEditor3gpReader_BitStreamParserFlushBits(
1366                    pBitParserContext, 8);
1367            }
1368        }
1369        VideoEditor3gpReader_BitStreamParserCleanUp(pBitParserContext);
1370        pStreamHandler->m_decoderSpecificInfoSize = uiSpecInfoSize;
1371        pStreamHandler->m_pDecoderSpecificInfo = (M4OSA_UInt8*)pAvcSpecInfo;
1372    }
1373    pStreamHandler->m_H264decoderSpecificInfoSize  =  decoderConfigSizeLocal;
1374    pStreamHandler->m_pH264DecoderSpecificInfo  = (M4OSA_UInt8*)M4OSA_32bitAlignedMalloc(
1375        decoderConfigSizeLocal, M4READER_3GP,
1376        (M4OSA_Char*)"MPEG-4 AVC DecoderSpecific");
1377    if (M4OSA_NULL == pStreamHandler->m_pH264DecoderSpecificInfo) {
1378        goto cleanup;
1379    }
1380
1381    memcpy((void * ) pStreamHandler->m_pH264DecoderSpecificInfo,
1382        (void * )pDecoderConfigLocal,
1383        pStreamHandler->m_H264decoderSpecificInfoSize);
1384    return M4NO_ERROR;
1385cleanup:
1386    VideoEditor3gpReader_BitStreamParserCleanUp(pBitParserContext);
1387    return M4ERR_READER3GP_DECODER_CONFIG_ERROR;
1388}
1389/**
1390********************************************************************************
1391* @brief    Get the next stream found in the 3gp file
1392* @note
1393* @param    context:     (IN)    Context of the reader
1394* @param    pMediaFamily: OUT)   pointer to a user allocated
1395*                                M4READER_MediaFamily that will be filled
1396*                                with the media family of the found stream
1397* @param    pStreamHandler:(OUT) pointer to StreamHandler that will be allocated
1398*                                and filled with the found stream description
1399* @return   M4NO_ERROR              there is no error
1400* @return   M4ERR_BAD_CONTEXT       provided context is not a valid one
1401* @return   M4ERR_PARAMETER         at least one parameter is not properly set
1402* @return   M4WAR_NO_MORE_STREAM    no more available stream in the media
1403********************************************************************************
1404*/
1405M4OSA_ERR VideoEditor3gpReader_getNextStreamHandler(M4OSA_Context context,
1406        M4READER_MediaFamily *pMediaFamily,
1407        M4_StreamHandler **pStreamHandler) {
1408    VideoEditor3gpReader_Context* pC=(VideoEditor3gpReader_Context*)context;
1409    M4OSA_ERR err = M4NO_ERROR;
1410    M4SYS_StreamID streamIdArray[2];
1411    M4SYS_StreamDescription streamDesc;
1412    M4_AudioStreamHandler* pAudioStreamHandler;
1413    M4_VideoStreamHandler* pVideoStreamHandler;
1414    M4OSA_Int8 *DecoderSpecificInfo = M4OSA_NULL;
1415    M4OSA_Int32 decoderSpecificInfoSize =0, maxAUSize = 0;
1416
1417    M4_StreamType streamType = M4DA_StreamTypeUnknown;
1418    M4OSA_UInt8 temp, i, trackCount;
1419    M4OSA_Bool haveAudio = M4OSA_FALSE;
1420    M4OSA_Bool haveVideo = M4OSA_FALSE;
1421    sp<MetaData> meta  = NULL;
1422    int64_t Duration = 0;
1423    M4OSA_UInt8* DecoderSpecific = M4OSA_NULL ;
1424    uint32_t type;
1425    const void *data;
1426    size_t size;
1427    const void *codec_specific_data;
1428    size_t codec_specific_data_size;
1429    M4OSA_Int32  ptempTime;
1430    M4OSA_Int32  avgFPS=0;
1431
1432    LOGV("VideoEditor3gpReader_getNextStreamHandler begin");
1433
1434    M4OSA_DEBUG_IF1((pC == 0), M4ERR_PARAMETER,
1435        "VideoEditor3gpReader_getNextStreamHandler: invalid context");
1436    M4OSA_DEBUG_IF1((pMediaFamily   == 0), M4ERR_PARAMETER,
1437        "getNextStreamHandler: invalid pointer to MediaFamily");
1438    M4OSA_DEBUG_IF1((pStreamHandler == 0), M4ERR_PARAMETER,
1439        "getNextStreamHandler: invalid pointer to StreamHandler");
1440
1441    trackCount = pC->mExtractor->countTracks();
1442    temp = pC->mCurrTrack;
1443
1444    if(temp >= trackCount) {
1445        LOGV("VideoEditor3gpReader_getNextStreamHandler error = %d",
1446            M4WAR_NO_MORE_STREAM);
1447        return (M4WAR_NO_MORE_STREAM);
1448    } else {
1449        const char *mime;
1450        meta = pC->mExtractor->getTrackMetaData(temp);
1451        CHECK(meta->findCString(kKeyMIMEType, &mime));
1452
1453        if (!haveVideo && !strncasecmp(mime, "video/", 6)) {
1454            pC->mVideoSource = pC->mExtractor->getTrack(temp);
1455            pC->mVideoSource->start();
1456
1457            *pMediaFamily = M4READER_kMediaFamilyVideo;
1458            haveVideo = true;
1459            LOGV("VideoEditor3gpReader_getNextStreamHandler getTrack called");
1460            if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
1461                streamType = M4DA_StreamTypeVideoMpeg4Avc;
1462            } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_H263)) {
1463                streamType = M4DA_StreamTypeVideoH263;
1464            } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4)) {
1465                streamType = M4DA_StreamTypeVideoMpeg4;
1466            } else {
1467                LOGV("VideoEditor3gpReaderGetNextStreamHandler streamTypeNONE");
1468            }
1469            LOGV("VideoEditor3gpReader_getNextStreamHandler: stream type: %d ",
1470                streamType);
1471
1472            if(streamType != M4DA_StreamTypeUnknown) {
1473                pC->mStreamType = streamType;
1474                pC->mStreamId = pC->mCurrTrack;
1475
1476                pVideoStreamHandler = (M4_VideoStreamHandler*)M4OSA_32bitAlignedMalloc
1477                    (sizeof(M4_VideoStreamHandler), M4READER_3GP,
1478                    (M4OSA_Char*)"M4_VideoStreamHandler");
1479                if (M4OSA_NULL == pVideoStreamHandler) {
1480                    return M4ERR_ALLOC;
1481                }
1482                pVideoStreamHandler->m_structSize=sizeof(M4_VideoStreamHandler);
1483
1484                meta->findInt32(kKeyWidth,
1485                    (int32_t*)&(pVideoStreamHandler->m_videoWidth));
1486                meta->findInt32(kKeyHeight,
1487                    (int32_t*)&(pVideoStreamHandler->m_videoHeight));
1488
1489                (*pStreamHandler)  = (M4_StreamHandler*)(pVideoStreamHandler);
1490                meta->findInt64(kKeyDuration,
1491                    (int64_t*)&(Duration));
1492                ((*pStreamHandler)->m_duration) =
1493                    (int32_t)((Duration)/1000); // conversion to mS
1494                pC->mMaxDuration = ((*pStreamHandler)->m_duration);
1495                LOGV("VideoEditor3gpReader_getNextStreamHandler m_duration %d",
1496                    (*pStreamHandler)->m_duration);
1497
1498                pC->mFileSize  = 0;
1499
1500                meta->findInt32(kKeyMaxInputSize, (int32_t*)&(maxAUSize));
1501                if(maxAUSize == 0) {
1502                    maxAUSize = 70000;
1503                }
1504                (*pStreamHandler)->m_maxAUSize = maxAUSize;
1505                LOGV("<<<<<<<<<<   video: mMaxAUSize from MP4 extractor: %d",
1506                    (*pStreamHandler)->m_maxAUSize);
1507
1508                if( (M4DA_StreamTypeVideoH263       == streamType) ||
1509                    (M4DA_StreamTypeVideoMpeg4Avc   == streamType)){
1510                    ((M4_StreamHandler*)pVideoStreamHandler)->m_averageBitRate =
1511                        384000;
1512                }
1513
1514                meta->findInt32(kKeyFrameRate,
1515                    (int32_t*)&(avgFPS));
1516                LOGV("<<<<<<<<<<   video: Average FPS from MP4 extractor: %d",
1517                    avgFPS);
1518
1519                pVideoStreamHandler->m_averageFrameRate =(M4OSA_Float) avgFPS;
1520                LOGV("<<<<<<<<<<   video: Average FPS from MP4 extractor in FLOAT: %f",
1521                    pVideoStreamHandler->m_averageFrameRate);
1522
1523                pC->mVideoStreamHandler =
1524                    (M4_StreamHandler*)(pVideoStreamHandler);
1525
1526                /* Get the DSI info */
1527                if(M4DA_StreamTypeVideoH263 == streamType) {
1528                    if (meta->findData(kKeyD263, &type, &data, &size)) {
1529                        (*pStreamHandler)->m_decoderSpecificInfoSize = size;
1530                        if ((*pStreamHandler)->m_decoderSpecificInfoSize != 0) {
1531                            DecoderSpecific = (M4OSA_UInt8*)M4OSA_32bitAlignedMalloc(
1532                                (*pStreamHandler)->m_decoderSpecificInfoSize,
1533                                M4READER_3GP,(M4OSA_Char*)"H263 DSI");
1534                            if (M4OSA_NULL == DecoderSpecific) {
1535                                return M4ERR_ALLOC;
1536                            }
1537                            memcpy((void *)DecoderSpecific,
1538                                (void *)data, size);
1539                            (*pStreamHandler)->m_pDecoderSpecificInfo =
1540                                DecoderSpecific;
1541                        }
1542                        else {
1543                            (*pStreamHandler)->m_pDecoderSpecificInfo =
1544                                M4OSA_NULL;
1545                            (*pStreamHandler)->m_decoderSpecificInfoSize = 0;
1546                        }
1547                        (*pStreamHandler)->m_pESDSInfo = M4OSA_NULL;
1548                        (*pStreamHandler)->m_ESDSInfoSize = 0;
1549                        (*pStreamHandler)->m_pH264DecoderSpecificInfo = M4OSA_NULL;
1550                        (*pStreamHandler)->m_H264decoderSpecificInfoSize = 0;
1551                    } else {
1552                        LOGV("VE_getNextStreamHandler: H263 dsi not found");
1553                        (*pStreamHandler)->m_pDecoderSpecificInfo = M4OSA_NULL;
1554                        (*pStreamHandler)->m_decoderSpecificInfoSize = 0;
1555                        (*pStreamHandler)->m_H264decoderSpecificInfoSize = 0;
1556                        (*pStreamHandler)->m_pH264DecoderSpecificInfo =
1557                            M4OSA_NULL;
1558                        (*pStreamHandler)->m_pESDSInfo = M4OSA_NULL;
1559                        (*pStreamHandler)->m_ESDSInfoSize = 0;
1560                    }
1561                }
1562                else if(M4DA_StreamTypeVideoMpeg4Avc == streamType) {
1563                    if(meta->findData(kKeyAVCC, &type, &data, &size)) {
1564                        decoderSpecificInfoSize = size;
1565                        if (decoderSpecificInfoSize != 0) {
1566                            DecoderSpecificInfo = (M4OSA_Int8*)M4OSA_32bitAlignedMalloc(
1567                                decoderSpecificInfoSize, M4READER_3GP,
1568                                (M4OSA_Char*)"H264 DecoderSpecific" );
1569                            if (M4OSA_NULL == DecoderSpecificInfo) {
1570                                LOGV("VideoEditor3gp_getNextStream is NULL ");
1571                                return M4ERR_ALLOC;
1572                            }
1573                            memcpy((void *)DecoderSpecificInfo,
1574                                (void *)data, decoderSpecificInfoSize);
1575                        } else {
1576                            LOGV("DSI Size %d", decoderSpecificInfoSize);
1577                            DecoderSpecificInfo = M4OSA_NULL;
1578                        }
1579                    }
1580                    (*pStreamHandler)->m_pESDSInfo = M4OSA_NULL;
1581                    (*pStreamHandler)->m_ESDSInfoSize = 0;
1582
1583                    err = VideoEditor3gpReader_AnalyseAvcDsi(*pStreamHandler,
1584                    (M4OSA_Int32*)DecoderSpecificInfo, decoderSpecificInfoSize);
1585
1586                    if (M4NO_ERROR != err) {
1587                        return err;
1588                    }
1589                    LOGV("decsize %d, h264decsize %d: %d", (*pStreamHandler)->\
1590                        m_decoderSpecificInfoSize, (*pStreamHandler)->\
1591                        m_H264decoderSpecificInfoSize);
1592
1593                    if(M4OSA_NULL != DecoderSpecificInfo) {
1594                        free(DecoderSpecificInfo);
1595                        DecoderSpecificInfo = M4OSA_NULL;
1596                    }
1597                } else if( (M4DA_StreamTypeVideoMpeg4 == streamType) ) {
1598                    if (meta->findData(kKeyESDS, &type, &data, &size)) {
1599                        ESDS esds((const char *)data, size);
1600                        CHECK_EQ(esds.InitCheck(), OK);
1601
1602                        (*pStreamHandler)->m_ESDSInfoSize = size;
1603                        (*pStreamHandler)->m_pESDSInfo = (M4OSA_UInt8*)\
1604                        M4OSA_32bitAlignedMalloc((*pStreamHandler)->m_ESDSInfoSize,
1605                        M4READER_3GP, (M4OSA_Char*)"H263 DecoderSpecific" );
1606                        if (M4OSA_NULL == (*pStreamHandler)->m_pESDSInfo) {
1607                            return M4ERR_ALLOC;
1608                        }
1609                        memcpy((void *)(*pStreamHandler)->\
1610                            m_pESDSInfo, (void *)data, size);
1611
1612                        esds.getCodecSpecificInfo(&codec_specific_data,
1613                            &codec_specific_data_size);
1614                        LOGV("VE MP4 dsisize: %d, %x", codec_specific_data_size,
1615                            codec_specific_data);
1616
1617                        (*pStreamHandler)->m_decoderSpecificInfoSize =
1618                            codec_specific_data_size;
1619                        if ((*pStreamHandler)->m_decoderSpecificInfoSize != 0) {
1620                            DecoderSpecific = (M4OSA_UInt8*)M4OSA_32bitAlignedMalloc(
1621                                (*pStreamHandler)->m_decoderSpecificInfoSize,
1622                                M4READER_3GP, (M4OSA_Char*)" DecoderSpecific" );
1623                            if (M4OSA_NULL == DecoderSpecific) {
1624                                return M4ERR_ALLOC;
1625                            }
1626                            memcpy((void *)DecoderSpecific,
1627                                (void *)codec_specific_data,
1628                                codec_specific_data_size);
1629                            (*pStreamHandler)->m_pDecoderSpecificInfo =
1630                                DecoderSpecific;
1631                        }
1632                        else {
1633                            (*pStreamHandler)->m_pDecoderSpecificInfo =
1634                                M4OSA_NULL;
1635                        }
1636                        (*pStreamHandler)->m_pH264DecoderSpecificInfo =
1637                            M4OSA_NULL;
1638                        (*pStreamHandler)->m_H264decoderSpecificInfoSize = 0;
1639                    }
1640                } else {
1641                    LOGV("VideoEditor3gpReader_getNextStream NO video stream");
1642                    return M4ERR_READER_UNKNOWN_STREAM_TYPE;
1643                }
1644            }
1645            else {
1646                LOGV("VideoEditor3gpReader_getNextStream NO video stream");
1647                return M4ERR_READER_UNKNOWN_STREAM_TYPE;
1648            }
1649
1650        } else if (!haveAudio && !strncasecmp(mime, "audio/", 6)) {
1651            LOGV("VideoEditor3gpReader_getNextStream audio getTrack called");
1652            pC->mAudioSource = pC->mExtractor->getTrack(pC->mCurrTrack);
1653            pC->mAudioSource->start();
1654            *pMediaFamily = M4READER_kMediaFamilyAudio;
1655
1656            if(!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_NB)) {
1657                streamType = M4DA_StreamTypeAudioAmrNarrowBand;
1658            } else if(!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_WB)) {
1659                streamType = M4DA_StreamTypeAudioAmrWideBand;
1660            }
1661            else if(!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
1662                streamType = M4DA_StreamTypeAudioAac;
1663            } else {
1664                LOGV("VideoEditor3gpReader_getNextStrea streamtype Unknown ");
1665            }
1666            if(streamType != M4DA_StreamTypeUnknown) {
1667                pC->mStreamType = streamType;
1668                pC->mStreamId = pC->mCurrTrack;
1669
1670                LOGV("VE streamtype %d ,id %d",  streamType, pC->mCurrTrack);
1671
1672                pAudioStreamHandler = (M4_AudioStreamHandler*)M4OSA_32bitAlignedMalloc
1673                    (sizeof(M4_AudioStreamHandler), M4READER_3GP,
1674                    (M4OSA_Char*)"M4_AudioStreamHandler");
1675                if (M4OSA_NULL == pAudioStreamHandler) {
1676                    return M4ERR_ALLOC;
1677                }
1678                pAudioStreamHandler->m_structSize=sizeof(M4_AudioStreamHandler);
1679                pAudioStreamHandler->m_byteSampleSize   = 0;
1680                pAudioStreamHandler->m_nbChannels       = 0;
1681                pAudioStreamHandler->m_samplingFrequency= 0;
1682                pAudioStreamHandler->m_byteFrameLength  = 0;
1683
1684                (*pStreamHandler) = (M4_StreamHandler*)(pAudioStreamHandler);
1685                pC->mAudioStreamHandler =
1686                    (M4_StreamHandler*)(pAudioStreamHandler);
1687                (*pStreamHandler)->m_averageBitRate = 0;
1688                haveAudio = true;
1689                pC->mAudioStreamHandler=(M4_StreamHandler*)pAudioStreamHandler;
1690                pC->mAudioStreamHandler->m_pESDSInfo = M4OSA_NULL;
1691                pC->mAudioStreamHandler->m_ESDSInfoSize = 0;
1692
1693                meta->findInt32(kKeyMaxInputSize, (int32_t*)&(maxAUSize));
1694                if(maxAUSize == 0) {
1695                    maxAUSize = 70000;
1696                }
1697                (*pStreamHandler)->m_maxAUSize = maxAUSize;
1698                LOGV("VE Audio mMaxAUSize from MP4 extractor: %d", maxAUSize);
1699            }
1700            if((M4DA_StreamTypeAudioAmrNarrowBand == streamType) ||
1701                (M4DA_StreamTypeAudioAmrWideBand == streamType)) {
1702                M4OSA_UInt32 freqIndex = 0; /**< AMR NB */
1703                M4OSA_UInt32 modeSet;
1704                M4OSA_UInt32 i;
1705                M4OSA_Context pBitParserContext = M4OSA_NULL;
1706
1707                if(M4DA_StreamTypeAudioAmrWideBand == streamType) {
1708                    freqIndex = 1; /**< AMR WB */
1709                }
1710
1711                if (meta->findData(kKeyESDS, &type, &data, &size)) {
1712                    ESDS esds((const char *)data, size);
1713                    CHECK_EQ(esds.InitCheck(), OK);
1714
1715                    esds.getCodecSpecificInfo(&codec_specific_data,
1716                        &codec_specific_data_size);
1717                    (*pStreamHandler)->m_decoderSpecificInfoSize =
1718                        codec_specific_data_size;
1719
1720                    if ((*pStreamHandler)->m_decoderSpecificInfoSize != 0) {
1721                        DecoderSpecific = (M4OSA_UInt8*)M4OSA_32bitAlignedMalloc(
1722                            (*pStreamHandler)->m_decoderSpecificInfoSize,
1723                            M4READER_3GP, (M4OSA_Char*)"H263 DecoderSpecific" );
1724                        if (M4OSA_NULL == DecoderSpecific) {
1725                            return M4ERR_ALLOC;
1726                        }
1727                        memcpy((void *)DecoderSpecific,
1728                            (void *)codec_specific_data,
1729                            codec_specific_data_size);
1730                        (*pStreamHandler)->m_pDecoderSpecificInfo =
1731                            DecoderSpecific;
1732                    } else {
1733                        (*pStreamHandler)->m_pDecoderSpecificInfo = M4OSA_NULL;
1734                    }
1735                } else {
1736                    M4OSA_UChar AmrDsi[] =
1737                        {'P','H','L','P',0x00, 0x00, 0x80, 0x00, 0x01,};
1738                    (*pStreamHandler)->m_decoderSpecificInfoSize = 9;
1739                    DecoderSpecific = (M4OSA_UInt8*)M4OSA_32bitAlignedMalloc(
1740                        (*pStreamHandler)->m_decoderSpecificInfoSize,
1741                        M4READER_3GP, (M4OSA_Char*)"H263 DecoderSpecific" );
1742                    if (M4OSA_NULL == DecoderSpecific) {
1743                        return M4ERR_ALLOC;
1744                    }
1745                    if(freqIndex ==0) {
1746                        AmrDsi[8] = 0x01;
1747                    } else {
1748                        AmrDsi[8] = 0x02;
1749                    }
1750                    for(i = 0; i< 9; i++) {
1751                        DecoderSpecific[i] = AmrDsi[i];
1752                    }
1753                    (*pStreamHandler)->m_pDecoderSpecificInfo = DecoderSpecific;
1754                }
1755                (*pStreamHandler)->m_averageBitRate =
1756                    VideoEditor3gpReader_AmrBitRate[freqIndex][7];
1757            } else if((M4DA_StreamTypeAudioAac == streamType)) {
1758                if (meta->findData(kKeyESDS, &type, &data, &size)) {
1759                    ESDS esds((const char *)data, size);
1760                    CHECK_EQ(esds.InitCheck(), OK);
1761
1762                    (*pStreamHandler)->m_ESDSInfoSize = size;
1763                    (*pStreamHandler)->m_pESDSInfo = (M4OSA_UInt8*)M4OSA_32bitAlignedMalloc(
1764                        (*pStreamHandler)->m_ESDSInfoSize, M4READER_3GP,
1765                        (M4OSA_Char*)"H263 DecoderSpecific" );
1766                    if (M4OSA_NULL == (*pStreamHandler)->m_pESDSInfo) {
1767                        return M4ERR_ALLOC;
1768                    }
1769                    memcpy((void *)(*pStreamHandler)->m_pESDSInfo,
1770                    (void *)data, size);
1771                    esds.getCodecSpecificInfo(&codec_specific_data,
1772                        &codec_specific_data_size);
1773
1774                    LOGV("VEdsi %d,%x",codec_specific_data_size,
1775                        codec_specific_data);
1776
1777                    (*pStreamHandler)->m_decoderSpecificInfoSize =
1778                        codec_specific_data_size;
1779                    if ((*pStreamHandler)->m_decoderSpecificInfoSize != 0) {
1780                        DecoderSpecific = (M4OSA_UInt8*)M4OSA_32bitAlignedMalloc(
1781                            (*pStreamHandler)->m_decoderSpecificInfoSize,
1782                            M4READER_3GP, (M4OSA_Char*)"H263 DecoderSpecific" );
1783                        if (M4OSA_NULL == DecoderSpecific) {
1784                            return M4ERR_ALLOC;
1785                        }
1786                        memcpy((void *)DecoderSpecific,
1787                            (void *)codec_specific_data,
1788                            codec_specific_data_size);
1789                        (*pStreamHandler)->m_pDecoderSpecificInfo =
1790                            DecoderSpecific;
1791                    } else {
1792                        (*pStreamHandler)->m_pDecoderSpecificInfo = M4OSA_NULL;
1793                    }
1794                }
1795            } else {
1796                LOGV("VideoEditor3gpReader_getNextStream mStreamType: none ");
1797                return M4ERR_READER_UNKNOWN_STREAM_TYPE;
1798            }
1799        } else {
1800            LOGV("VE noaudio-video stream:pC->mCurrTrack = %d ",pC->mCurrTrack);
1801            pC->mCurrTrack++; //Increment current track to get the next track
1802            return M4ERR_READER_UNKNOWN_STREAM_TYPE;
1803        }
1804        LOGV("VE StreamType: %d, stremhandler %x",streamType, *pStreamHandler );
1805        (*pStreamHandler)->m_streamType = streamType;
1806        (*pStreamHandler)->m_streamId   = pC->mStreamId;
1807        (*pStreamHandler)->m_pUserData  = M4OSA_NULL;
1808        (*pStreamHandler)->m_structSize = sizeof(M4_StreamHandler);
1809        (*pStreamHandler)->m_bStreamIsOK = M4OSA_TRUE;
1810
1811        meta->findInt64(kKeyDuration,
1812            (int64_t*)&(Duration));
1813
1814        (*pStreamHandler)->m_duration = (int32_t)(Duration / 1000);
1815
1816        pC->mMaxDuration = ((*pStreamHandler)->m_duration);
1817        LOGV("VE str duration duration: %d ", (*pStreamHandler)->m_duration);
1818
1819        /* In AAC case: Put the first AU in pAudioStreamHandler->m_pUserData
1820         *since decoder has to know if stream contains SBR data(Implicit sig) */
1821        if(M4DA_StreamTypeAudioAac == (*pStreamHandler)->m_streamType) {
1822            M4READER_AudioSbrUserdata*  pAudioSbrUserdata;
1823
1824            pAudioSbrUserdata = (M4READER_AudioSbrUserdata*)M4OSA_32bitAlignedMalloc(
1825                sizeof(M4READER_AudioSbrUserdata),M4READER_3GP,
1826                (M4OSA_Char*)"M4READER_AudioSbrUserdata");
1827            if (M4OSA_NULL == pAudioSbrUserdata) {
1828                err = M4ERR_ALLOC;
1829                goto Error;
1830            }
1831            (*pStreamHandler)->m_pUserData = pAudioSbrUserdata;
1832            pAudioSbrUserdata->m_bIsSbrEnabled = M4OSA_FALSE;
1833
1834            pAudioSbrUserdata->m_pFirstAU = (M4_AccessUnit*)M4OSA_32bitAlignedMalloc(
1835                sizeof(M4_AccessUnit),M4READER_3GP, (M4OSA_Char*)"1st AAC AU");
1836            if (M4OSA_NULL == pAudioSbrUserdata->m_pFirstAU) {
1837                pAudioSbrUserdata->m_pAacDecoderUserConfig = M4OSA_NULL;
1838                err = M4ERR_ALLOC;
1839                goto Error;
1840            }
1841            pAudioSbrUserdata->m_pAacDecoderUserConfig = (M4_AacDecoderConfig*)\
1842                M4OSA_32bitAlignedMalloc(sizeof(M4_AacDecoderConfig),M4READER_3GP,
1843                (M4OSA_Char*)"m_pAacDecoderUserConfig");
1844            if (M4OSA_NULL == pAudioSbrUserdata->m_pAacDecoderUserConfig) {
1845                err = M4ERR_ALLOC;
1846                goto Error;
1847            }
1848        }
1849        if(M4DA_StreamTypeAudioAac == (*pStreamHandler)->m_streamType) {
1850            M4_AudioStreamHandler* pAudioStreamHandler =
1851                (M4_AudioStreamHandler*)(*pStreamHandler);
1852            M4READER_AudioSbrUserdata* pUserData = (M4READER_AudioSbrUserdata*)\
1853                (pAudioStreamHandler->m_basicProperties.m_pUserData);
1854
1855            err = VideoEditor3gpReader_fillAuStruct(pC, (*pStreamHandler),
1856                (M4_AccessUnit*)pUserData->m_pFirstAU);
1857            if (M4NO_ERROR != err) {
1858                goto Error;
1859            }
1860            err = VideoEditor3gpReader_getNextAu(pC, (*pStreamHandler),
1861                (M4_AccessUnit*)pUserData->m_pFirstAU);
1862            if (M4NO_ERROR != err) {
1863                goto Error;
1864            }
1865            err = VideoEditor3gpReader_reset(pC, (*pStreamHandler));
1866            if (M4NO_ERROR != err) {
1867                goto Error;
1868            }
1869        }
1870    }
1871    pC->mCurrTrack++; //Increment the current track to get next track
1872    LOGV("pC->mCurrTrack = %d",pC->mCurrTrack);
1873
1874    if (!haveAudio && !haveVideo) {
1875        *pMediaFamily=M4READER_kMediaFamilyUnknown;
1876        return M4ERR_READER_UNKNOWN_STREAM_TYPE;
1877    }
1878Error:
1879    LOGV("VideoEditor3gpReader_getNextStreamHandler end error = %d",err);
1880    return err;
1881}
1882
1883M4OSA_ERR VideoEditor3gpReader_getPrevRapTime(M4OSA_Context context,
1884    M4_StreamHandler *pStreamHandler, M4OSA_Int32* pTime)
1885{
1886    VideoEditor3gpReader_Context *pC = (VideoEditor3gpReader_Context*)context;
1887    M4OSA_ERR err = M4NO_ERROR;
1888    MediaBuffer *mMediaBuffer = M4OSA_NULL;
1889    MediaSource::ReadOptions options;
1890    M4OSA_Time time64;
1891    int64_t tempTime64 = 0;
1892    status_t error;
1893
1894    LOGV("VideoEditor3gpReader_getPrevRapTime begin");
1895
1896    M4OSA_DEBUG_IF1((pC == 0), M4ERR_PARAMETER,
1897        "VideoEditor3gpReader_getPrevRapTime: invalid context");
1898    M4OSA_DEBUG_IF1((pStreamHandler == 0), M4ERR_PARAMETER,
1899        "VideoEditor3gpReader_getPrevRapTime invalid pointer to StreamHandler");
1900    M4OSA_DEBUG_IF1((pTime == 0), M4ERR_PARAMETER,
1901        "VideoEditor3gpReader_getPrevRapTime: invalid time pointer");
1902    if (*pTime == (pStreamHandler->m_duration)) {
1903        *pTime -= 1;
1904    }
1905
1906    time64 = (M4OSA_Time)*pTime * 1000;
1907
1908    LOGV("VideoEditor3gpReader_getPrevRapTime seek time: %ld",time64);
1909    options.setSeekTo(time64, MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC);
1910    error = pC->mVideoSource->read(&mMediaBuffer, &options);
1911    if (error != OK) {
1912        //Can not get the previous Sync.
1913        //Must be end of stream.
1914        return M4WAR_NO_MORE_AU;
1915    }
1916
1917    mMediaBuffer->meta_data()->findInt64(kKeyTime, (int64_t*)&tempTime64);
1918    LOGV("VideoEditor3gpReader_getPrevRapTime read time %ld, %x", tempTime64,
1919        mMediaBuffer);
1920
1921    *pTime = (M4OSA_Int32)(tempTime64 / 1000);
1922
1923    if(mMediaBuffer != M4OSA_NULL) {
1924        LOGV(" mMediaBuffer size = %d length %d", mMediaBuffer->size(),
1925            mMediaBuffer->range_length());
1926        mMediaBuffer->release();
1927        mMediaBuffer = M4OSA_NULL;
1928    }
1929    options.clearSeekTo();
1930
1931    if(error != OK) {
1932        LOGV("VideoEditor3gpReader_getPrevRapTime end \
1933            M4WAR_READER_INFORMATION_NOT_PRESENT");
1934        return M4WAR_READER_INFORMATION_NOT_PRESENT;
1935    } else {
1936        LOGV("VideoEditor3gpReader_getPrevRapTime end: err %x", err);
1937        err = M4NO_ERROR;
1938        return err;
1939    }
1940}
1941
1942extern "C" {
1943M4OSA_ERR VideoEditor3gpReader_getInterface(M4READER_MediaType *pMediaType,
1944        M4READER_GlobalInterface **pRdrGlobalInterface,
1945        M4READER_DataInterface **pRdrDataInterface) {
1946
1947    M4OSA_ERR err = M4NO_ERROR;
1948
1949    VIDEOEDITOR_CHECK(M4OSA_NULL != pMediaType,      M4ERR_PARAMETER);
1950    VIDEOEDITOR_CHECK(M4OSA_NULL != pRdrGlobalInterface, M4ERR_PARAMETER);
1951    VIDEOEDITOR_CHECK(M4OSA_NULL != pRdrDataInterface, M4ERR_PARAMETER);
1952
1953    LOGV("VideoEditor3gpReader_getInterface begin");
1954    LOGV("VideoEditor3gpReader_getInterface %d 0x%x 0x%x", *pMediaType,
1955        *pRdrGlobalInterface,*pRdrDataInterface);
1956
1957    SAFE_MALLOC(*pRdrGlobalInterface, M4READER_GlobalInterface, 1,
1958        "VideoEditor3gpReader_getInterface");
1959    SAFE_MALLOC(*pRdrDataInterface, M4READER_DataInterface, 1,
1960        "VideoEditor3gpReader_getInterface");
1961
1962    *pMediaType = M4READER_kMediaType3GPP;
1963
1964    (*pRdrGlobalInterface)->m_pFctCreate       = VideoEditor3gpReader_create;
1965    (*pRdrGlobalInterface)->m_pFctDestroy      = VideoEditor3gpReader_destroy;
1966    (*pRdrGlobalInterface)->m_pFctOpen         = VideoEditor3gpReader_open;
1967    (*pRdrGlobalInterface)->m_pFctClose        = VideoEditor3gpReader_close;
1968    (*pRdrGlobalInterface)->m_pFctGetOption    = VideoEditor3gpReader_getOption;
1969    (*pRdrGlobalInterface)->m_pFctSetOption    = VideoEditor3gpReader_setOption;
1970    (*pRdrGlobalInterface)->m_pFctGetNextStream =
1971        VideoEditor3gpReader_getNextStreamHandler;
1972    (*pRdrGlobalInterface)->m_pFctFillAuStruct =
1973        VideoEditor3gpReader_fillAuStruct;
1974    (*pRdrGlobalInterface)->m_pFctStart        = M4OSA_NULL;
1975    (*pRdrGlobalInterface)->m_pFctStop         = M4OSA_NULL;
1976    (*pRdrGlobalInterface)->m_pFctJump         = VideoEditor3gpReader_jump;
1977    (*pRdrGlobalInterface)->m_pFctReset        = VideoEditor3gpReader_reset;
1978    (*pRdrGlobalInterface)->m_pFctGetPrevRapTime =
1979        VideoEditor3gpReader_getPrevRapTime;
1980    (*pRdrDataInterface)->m_pFctGetNextAu      = VideoEditor3gpReader_getNextAu;
1981    (*pRdrDataInterface)->m_readerContext      = M4OSA_NULL;
1982
1983cleanUp:
1984    if( M4NO_ERROR == err ) {
1985        LOGV("VideoEditor3gpReader_getInterface no error");
1986    } else {
1987        SAFE_FREE(*pRdrGlobalInterface);
1988        SAFE_FREE(*pRdrDataInterface);
1989
1990        LOGV("VideoEditor3gpReader_getInterface ERROR 0x%X", err);
1991    }
1992    LOGV("VideoEditor3gpReader_getInterface end");
1993    return err;
1994}
1995
1996}  /* extern "C" */
1997
1998}  /* namespace android */
1999
2000
2001