VideoEditor3gpReader.cpp revision 3ad01762633531957174c5b27e71ca4aac45e554
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_malloc(
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    M4OSA_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    M4OSA_INT64_FROM_INT32(pC->mMaxDuration, 0);
410    *pContext=pC;
411
412cleanUp:
413    if ( M4NO_ERROR == err ) {
414        LOGV("VideoEditor3gpReader_create no error");
415    } else {
416        LOGV("VideoEditor3gpReader_create ERROR 0x%X", err);
417    }
418    LOGV("VideoEditor3gpReader_create end ");
419    return err;
420}
421
422/**
423**************************************************************************
424* @brief    destroy the instance of the 3gp reader
425* @note after this call the context is invalid
426* @param    context:        (IN)    Context of the reader
427* @return   M4NO_ERROR              there is no error
428* @return   M4ERR_PARAMETER         pContext parameter is not properly set
429**************************************************************************
430*/
431
432M4OSA_ERR VideoEditor3gpReader_destroy(M4OSA_Context pContext) {
433    M4OSA_ERR err = M4NO_ERROR;
434    VideoEditor3gpReader_Context* pC = M4OSA_NULL;
435
436    LOGV("VideoEditor3gpReader_destroy begin");
437
438    VIDEOEDITOR_CHECK(M4OSA_NULL != pContext, M4ERR_PARAMETER);
439    pC = (VideoEditor3gpReader_Context*)pContext;
440
441    SAFE_FREE(pC->mAudioAu.dataAddress);
442    pC->mAudioAu.dataAddress = M4OSA_NULL;
443    SAFE_FREE(pC->mVideoAu.dataAddress);
444    pC->mVideoAu.dataAddress = M4OSA_NULL;
445    SAFE_FREE(pC);
446    pContext = M4OSA_NULL;
447
448cleanUp:
449    if( M4NO_ERROR == err ) {
450        LOGV("VideoEditor3gpReader_destroy no error");
451    }
452    else
453    {
454        LOGV("VideoEditor3gpReader_destroy ERROR 0x%X", err);
455    }
456
457    LOGV("VideoEditor3gpReader_destroy end ");
458    return err;
459}
460
461/**
462************************************************************************
463* @brief    open the reader and initializes its created instance
464* @note     this function open the media file
465* @param    context:            (IN)    Context of the reader
466* @param    pFileDescriptor:    (IN)    Pointer to proprietary data identifying
467*                                       the media to open
468* @return   M4NO_ERROR                  there is no error
469* @return   M4ERR_PARAMETER             the context is NULL
470************************************************************************
471*/
472
473M4OSA_ERR VideoEditor3gpReader_open(M4OSA_Context pContext,
474        M4OSA_Void* pFileDescriptor) {
475    VideoEditor3gpReader_Context* pC = (VideoEditor3gpReader_Context*)pContext;
476    M4OSA_ERR err = M4NO_ERROR;
477
478    LOGV("VideoEditor3gpReader_open start ");
479    M4OSA_DEBUG_IF1((M4OSA_NULL == pC),  M4ERR_PARAMETER,
480        "VideoEditor3gpReader_open: invalid context pointer");
481    M4OSA_DEBUG_IF1((M4OSA_NULL == pFileDescriptor), M4ERR_PARAMETER,
482        "VideoEditor3gpReader_open: invalid pointer pFileDescriptor");
483
484    LOGV("VideoEditor3gpReader_open Datasource start %s",
485        (char*)pFileDescriptor);
486    //pC->mDataSource = DataSource::CreateFromURI((char*)pFileDescriptor);
487    pC->mDataSource = new FileSource ((char*)pFileDescriptor);
488
489    if (pC->mDataSource == NULL) {
490        LOGV("VideoEditor3gpReader_open Datasource error");
491        return M4ERR_PARAMETER;
492    }
493
494    pC->mExtractor = MediaExtractor::Create(pC->mDataSource,
495        MEDIA_MIMETYPE_CONTAINER_MPEG4);
496
497    if (pC->mExtractor == NULL) {
498        LOGV("VideoEditor3gpReader_open extractor error");
499        return M4ERR_PARAMETER;
500    }
501
502    LOGV("VideoEditor3gpReader_open end ");
503    return err;
504}
505
506/**
507************************************************************************
508* @brief    close the reader
509* @note     close the 3GP file
510* @param    context:        (IN)    Context of the reader
511* @return   M4NO_ERROR              there is no error
512* @return   M4ERR_PARAMETER         the context is NULL
513* @return   M4ERR_BAD_CONTEXT       provided context is not a valid one
514************************************************************************
515*/
516M4OSA_ERR VideoEditor3gpReader_close(M4OSA_Context context) {
517    VideoEditor3gpReader_Context *pC = (VideoEditor3gpReader_Context*)context;
518    M4READER_AudioSbrUserdata *pAudioSbrUserData;
519    M4_AccessUnit *pAU;
520    M4OSA_ERR err = M4NO_ERROR;
521
522    LOGV("VideoEditor3gpReader_close begin");
523
524    M4OSA_DEBUG_IF1((M4OSA_NULL == pC), M4ERR_PARAMETER,
525        "VideoEditor3gpReader_close: invalid context pointer");
526
527    if (pC->mAudioStreamHandler) {
528        LOGV("VideoEditor3gpReader_close Audio");
529
530        if (M4OSA_NULL != pC->mAudioStreamHandler->m_pDecoderSpecificInfo) {
531            M4OSA_free((M4OSA_MemAddr32)pC->mAudioStreamHandler->\
532                m_pDecoderSpecificInfo);
533            pC->mAudioStreamHandler->m_decoderSpecificInfoSize = 0;
534            pC->mAudioStreamHandler->m_pDecoderSpecificInfo = M4OSA_NULL;
535        }
536
537        if ((M4DA_StreamTypeAudioAac == pC->mAudioStreamHandler->m_streamType)
538            && (M4OSA_NULL != pC->mAudioStreamHandler->m_pUserData)) {
539            pAudioSbrUserData = (M4READER_AudioSbrUserdata*)(\
540                pC->mAudioStreamHandler->m_pUserData);
541
542            pAU = (M4_AccessUnit*)pAudioSbrUserData->m_pFirstAU;
543            if (M4OSA_NULL != pAU) {
544                M4OSA_free((M4OSA_MemAddr32)pAU);
545            }
546
547            if (M4OSA_NULL != pAudioSbrUserData->m_pAacDecoderUserConfig) {
548                M4OSA_free((M4OSA_MemAddr32)pAudioSbrUserData->\
549                    m_pAacDecoderUserConfig);
550            }
551            M4OSA_free((M4OSA_MemAddr32)pAudioSbrUserData);
552            pC->mAudioStreamHandler->m_pUserData = M4OSA_NULL;
553        }
554
555        if (pC->mAudioStreamHandler->m_pESDSInfo != M4OSA_NULL) {
556            M4OSA_free((M4OSA_MemAddr32)pC->mAudioStreamHandler->m_pESDSInfo);
557            pC->mAudioStreamHandler->m_pESDSInfo = M4OSA_NULL;
558            pC->mAudioStreamHandler->m_ESDSInfoSize = 0;
559        }
560        /* Finally destroy the stream handler */
561        M4OSA_free((M4OSA_MemAddr32)pC->mAudioStreamHandler);
562        pC->mAudioStreamHandler = M4OSA_NULL;
563
564        pC->mAudioSource->stop();
565        pC->mAudioSource.clear();
566    }
567    if (pC->mVideoStreamHandler) {
568        LOGV("VideoEditor3gpReader_close Video ");
569
570        if(M4OSA_NULL != pC->mVideoStreamHandler->m_pDecoderSpecificInfo) {
571            M4OSA_free((M4OSA_MemAddr32)pC->mVideoStreamHandler->\
572                m_pDecoderSpecificInfo);
573            pC->mVideoStreamHandler->m_decoderSpecificInfoSize = 0;
574            pC->mVideoStreamHandler->m_pDecoderSpecificInfo = M4OSA_NULL;
575        }
576
577        if(M4OSA_NULL != pC->mVideoStreamHandler->m_pH264DecoderSpecificInfo) {
578            M4OSA_free((M4OSA_MemAddr32)pC->mVideoStreamHandler->\
579                m_pH264DecoderSpecificInfo);
580            pC->mVideoStreamHandler->m_H264decoderSpecificInfoSize = 0;
581            pC->mVideoStreamHandler->m_pH264DecoderSpecificInfo = M4OSA_NULL;
582        }
583
584        if(pC->mVideoStreamHandler->m_pESDSInfo != M4OSA_NULL) {
585            M4OSA_free((M4OSA_MemAddr32)pC->mVideoStreamHandler->m_pESDSInfo);
586            pC->mVideoStreamHandler->m_pESDSInfo = M4OSA_NULL;
587            pC->mVideoStreamHandler->m_ESDSInfoSize = 0;
588        }
589
590        /* Finally destroy the stream handler */
591        M4OSA_free((M4OSA_MemAddr32)pC->mVideoStreamHandler);
592        pC->mVideoStreamHandler = M4OSA_NULL;
593
594        pC->mVideoSource->stop();
595        pC->mVideoSource.clear();
596    }
597    pC->mExtractor.clear();
598    pC->mDataSource.clear();
599
600    LOGV("VideoEditor3gpReader_close end");
601    return err;
602}
603
604/**
605************************************************************************
606* @brief    get an option from the 3gp reader
607* @note     it allows the caller to retrieve a property value:
608*
609* @param    context:        (IN)    Context of the reader
610* @param    optionId:       (IN)    indicates the option to get
611* @param    pValue:         (OUT)   pointer to structure or value (allocated
612*                                   by user) where option is stored
613*
614* @return   M4NO_ERROR              there is no error
615* @return   M4ERR_BAD_CONTEXT       provided context is not a valid one
616* @return   M4ERR_PARAMETER         at least one parameter is not properly set
617* @return   M4ERR_BAD_OPTION_ID     when the option ID is not a valid one
618* @return   M4ERR_VIDEO_NOT_H263    No video stream H263 in file.
619* @return   M4ERR_NO_VIDEO_STREAM_RETRIEVED_YET
620*           Function 3gpReader_getNextStreamHandler must be called before
621************************************************************************
622*/
623M4OSA_ERR VideoEditor3gpReader_getOption(M4OSA_Context context,
624        M4OSA_OptionID optionId, M4OSA_DataOption pValue) {
625    VideoEditor3gpReader_Context* pC = (VideoEditor3gpReader_Context*)context;
626    M4OSA_ERR err = M4NO_ERROR;
627
628    LOGV("VideoEditor3gpReader_getOption begin %d", optionId);
629
630    M4OSA_DEBUG_IF1((M4OSA_NULL == pC), M4ERR_PARAMETER,
631        "invalid context pointer");
632    M4OSA_DEBUG_IF1((M4OSA_NULL == pValue), M4ERR_PARAMETER,
633        "VideoEditor3gpReader_getOption: invalid pointer on value");
634
635    switch (optionId) {
636    case M4READER_kOptionID_Duration:
637        {
638            LOGV("VideoEditor3gpReader_getOption duration %d",pC->mMaxDuration);
639            M4OSA_TIME_SET(*(M4OSA_Time*)pValue, pC->mMaxDuration);
640        }
641        break;
642    case M4READER_kOptionID_Version:
643        /* not used */
644        LOGV("VideoEditor3gpReader_getOption: M4READER_kOptionID_Version");
645        break;
646
647    case M4READER_kOptionID_Copyright:
648        /* not used */
649        LOGV(">>>>>>>   M4READER_kOptionID_Copyright");
650        break;
651
652    case M4READER_kOptionID_CreationTime:
653        /* not used */
654        LOGV("VideoEditor3gpReader_getOption M4READER_kOptionID_CreationTime");
655    break;
656
657    case M4READER_kOptionID_Bitrate:
658        {
659            M4OSA_UInt32* pBitrate = (M4OSA_UInt32*)pValue;
660
661            if (pC->mMaxDuration != 0) {
662                M4OSA_UInt32 ui32Tmp = (M4OSA_UInt32)pC->mMaxDuration;
663                *pBitrate = (M4OSA_UInt32)((M4OSA_Double)pC->mFileSize * \
664                    8000.0 / (M4OSA_Double)ui32Tmp);
665                LOGV("3gpReader_getOption bitrate:  %d", *pBitrate);
666            }
667            *pBitrate = 384000; //check
668            LOGV("VideoEditor3gpReader_getOption bitrate %ld", *pBitrate);
669        }
670    break;
671    case M4READER_3GP_kOptionID_H263Properties:
672        {
673#if 0
674            if(M4OSA_NULL == pC->mVideoStreamHandler) {
675                LOGV("VideoEditor3gpReader_getOption no videoStream retrieved");
676
677                err = M4ERR_NO_VIDEO_STREAM_RETRIEVED_YET;
678                break;
679            }
680            if((M4DA_StreamTypeVideoH263 != pC->mVideoStreamHandler->\
681                mStreamType) || (pC->mVideoStreamHandler->\
682                m_decoderSpecificInfoSize < 7)) {
683                LOGV("VideoEditor3gpReader_getOption DSI Size %d",
684                    pC->mVideoStreamHandler->m_decoderSpecificInfoSize);
685
686                err = M4ERR_VIDEO_NOT_H263;
687                break;
688            }
689
690            /* MAGICAL in the decoder confi H263: the 7th byte is the profile
691             * number, 6th byte is the level number */
692            ((M4READER_3GP_H263Properties *)pValue)->uiProfile =
693                pC->mVideoStreamHandler->m_pDecoderSpecificInfo[6];
694            ((M4READER_3GP_H263Properties *)pValue)->uiLevel =
695                pC->mVideoStreamHandler->m_pDecoderSpecificInfo[5];
696#endif
697            LOGV("VideoEditor3gpReader_getOption M4READER_3GP_kOptionID_\
698            H263Properties end");
699        }
700        break;
701    case M4READER_3GP_kOptionID_PurpleLabsDrm:
702        LOGV("VideoEditor3gpReaderOption M4READER_3GP_kOptionID_PurpleLabsDrm");
703        /* not used */
704        break;
705
706    case M4READER_kOptionID_GetNumberOfAudioAu:
707        /* not used */
708        LOGV("VideoEditor3gpReadeOption M4READER_kOptionID_GetNumberOfAudioAu");
709    break;
710
711    case M4READER_kOptionID_GetNumberOfVideoAu:
712        /* not used */
713        LOGV("VideoEditor3gpReader_getOption :GetNumberOfVideoAu");
714    break;
715
716    case M4READER_kOptionID_GetMetadata:
717        /* not used */
718        LOGV("VideoEditor3gpReader_getOption M4READER_kOptionID_GetMetadata");
719    break;
720
721    case M4READER_kOptionID_3gpFtypBox:
722        /* used only for SEMC */
723        LOGV("VideoEditor3gpReader_getOption M4READER_kOptionID_3gpFtypBox");
724        err = M4ERR_BAD_OPTION_ID; //check this
725        break;
726
727#ifdef OPTIONID_GET_NEXT_VIDEO_CTS
728    case M4READER_3GP_kOptionID_getNextVideoCTS:
729        /* not used */
730        LOGV("VideoEditor3gpReader_getOption: getNextVideoCTS");
731        break;
732#endif
733    default:
734        {
735            err = M4ERR_BAD_OPTION_ID;
736            LOGV("VideoEditor3gpReader_getOption M4ERR_BAD_OPTION_ID");
737        }
738        break;
739    }
740    LOGV("VideoEditor3gpReader_getOption end: optionID: x%x", optionId);
741    return err;
742}
743/**
744************************************************************************
745* @brief    set an option on the 3gp reader
746* @note No option can be set yet.
747* @param    context:        (IN)    Context of the reader
748* @param    optionId:       (IN)    indicates the option to set
749* @param    pValue:         (IN)    pointer to structure or value (allocated
750*                                   by user) where option is stored
751* @return   M4NO_ERROR              there is no error
752* @return   M4ERR_BAD_CONTEXT       provided context is not a valid one
753* @return   M4ERR_PARAMETER         at least one parameter is not properly set
754* @return   M4ERR_BAD_OPTION_ID     when the option ID is not a valid one
755************************************************************************
756*/
757M4OSA_ERR VideoEditor3gpReader_setOption(M4OSA_Context context,
758        M4OSA_OptionID optionId, M4OSA_DataOption pValue) {
759    VideoEditor3gpReader_Context* pC = (VideoEditor3gpReader_Context*)context;
760    M4OSA_ERR err = M4NO_ERROR;
761
762    /* Check function parameters */
763    M4OSA_DEBUG_IF1((M4OSA_NULL == pC), M4ERR_PARAMETER,
764        "invalid context pointer");
765    M4OSA_DEBUG_IF1((M4OSA_NULL == pValue), M4ERR_PARAMETER,
766        "invalid value pointer");
767
768    LOGV("VideoEditor3gpReader_setOption begin %d",optionId);
769
770    switch(optionId) {
771        case M4READER_kOptionID_SetOsaFileReaderFctsPtr:
772        break;
773
774        case M4READER_3GP_kOptionID_AudioOnly:
775        break;
776
777        case M4READER_3GP_kOptionID_VideoOnly:
778        break;
779
780        case M4READER_3GP_kOptionID_FastOpenMode:
781        break;
782
783        case M4READER_kOptionID_MaxMetadataSize:
784        break;
785
786        default:
787        {
788            LOGV("VideoEditor3gpReader_setOption: returns M4ERR_BAD_OPTION_ID");
789            err = M4ERR_BAD_OPTION_ID;
790        }
791        break;
792    }
793    LOGV("VideoEditor3gpReader_setOption end ");
794    return err;
795}
796/**
797 ************************************************************************
798 * @brief   fill the access unit structure with initialization values
799 * @param   context:        (IN)     Context of the reader
800 * @param   pStreamHandler: (IN)     pointer to the stream handler to which
801 *                                   the access unit will be associated
802 * @param   pAccessUnit:    (IN/OUT) pointer to the access unit (allocated
803 *                                   by the caller) to initialize
804 * @return  M4NO_ERROR               there is no error
805 * @return  M4ERR_PARAMETER          at least one parameter is not properly set
806 ************************************************************************
807*/
808M4OSA_ERR VideoEditor3gpReader_fillAuStruct(M4OSA_Context context,
809        M4_StreamHandler *pStreamHandler, M4_AccessUnit *pAccessUnit) {
810    VideoEditor3gpReader_Context* pC = (VideoEditor3gpReader_Context*)context;
811    M4OSA_ERR err= M4NO_ERROR;
812
813    M4OSA_DEBUG_IF1((pC == 0),             M4ERR_PARAMETER,
814        "VideoEditor3gpReader_fillAuStruct: invalid context");
815    M4OSA_DEBUG_IF1((pStreamHandler == 0), M4ERR_PARAMETER,
816        "VideoEditor3gpReader_fillAuStruc invalid pointer to M4_StreamHandler");
817    M4OSA_DEBUG_IF1((pAccessUnit == 0),    M4ERR_PARAMETER,
818        "VideoEditor3gpReader_fillAuStruct: invalid pointer to M4_AccessUnit");
819
820    LOGV("VideoEditor3gpReader_fillAuStruct begin");
821
822    /* Initialize pAccessUnit structure */
823    pAccessUnit->m_size         = 0;
824    pAccessUnit->m_CTS          = 0;
825    pAccessUnit->m_DTS          = 0;
826    pAccessUnit->m_attribute    = 0;
827    pAccessUnit->m_dataAddress  = M4OSA_NULL;
828    pAccessUnit->m_maxsize      = pStreamHandler->m_maxAUSize;
829    pAccessUnit->m_streamID     = pStreamHandler->m_streamId;
830    pAccessUnit->m_structSize   = sizeof(M4_AccessUnit);
831
832    LOGV("VideoEditor3gpReader_fillAuStruct end");
833    return M4NO_ERROR;
834}
835
836/**
837********************************************************************************
838* @brief    jump into the stream at the specified time
839* @note
840* @param    context:        (IN)   Context of the reader
841* @param    pStreamHandler  (IN)   the stream handler of the stream to make jump
842* @param    pTime           (I/O)IN  the time to jump to (in ms)
843*                                OUT the time to which the stream really jumped
844* @return   M4NO_ERROR             there is no error
845* @return   M4ERR_PARAMETER        at least one parameter is not properly set
846********************************************************************************
847*/
848M4OSA_ERR VideoEditor3gpReader_jump(M4OSA_Context context,
849        M4_StreamHandler *pStreamHandler, M4OSA_Int32* pTime) {
850    VideoEditor3gpReader_Context* pC = (VideoEditor3gpReader_Context*)context;
851    M4OSA_ERR err = M4NO_ERROR;
852    M4SYS_AccessUnit* pAu;
853    M4OSA_Time time64;
854    M4OSA_Double timeDouble;
855
856    M4OSA_DEBUG_IF1((pC == 0), M4ERR_PARAMETER,
857        "VideoEditor3gpReader_jump: invalid context");
858    M4OSA_DEBUG_IF1((pStreamHandler == 0), M4ERR_PARAMETER,
859        "VideoEditor3gpReader_jump: invalid pointer to M4_StreamHandler");
860    M4OSA_DEBUG_IF1((pTime == 0), M4ERR_PARAMETER,
861        "VideoEditor3gpReader_jump: invalid time pointer");
862
863    LOGV("VideoEditor3gpReader_jump begin");
864
865    if (*pTime == (pStreamHandler->m_duration)) {
866        *pTime -= 1;
867    }
868    M4OSA_INT64_FROM_INT32(time64, *pTime);
869
870    LOGV("VideoEditor3gpReader_jump time us %ld ", time64);
871
872    if ((pC->mAudioStreamHandler != M4OSA_NULL) &&
873            (pStreamHandler->m_streamId == pC->mAudioStreamHandler->m_streamId))
874            {
875        pAu = &pC->mAudioAu;
876        pAu->CTS = time64;
877        pAu->DTS = time64;
878
879        time64 = time64 * 1000; /* Convert the time into micro sec */
880        pC->mAudioSeeking = M4OSA_TRUE;
881        pC->mAudioSeekTime = time64;
882        LOGV("VideoEditor3gpReader_jump AUDIO time us %ld ", time64);
883    } else if ((pC->mVideoStreamHandler != M4OSA_NULL) &&
884            (pStreamHandler->m_streamId == pC->mVideoStreamHandler->m_streamId))
885            {
886        pAu = &pC->mVideoAu;
887        pAu->CTS = time64;
888        pAu->DTS = time64;
889
890        time64 = time64 * 1000; /* Convert the time into micro sec */
891        pC->mVideoSeeking = M4OSA_TRUE;
892        pC->mVideoSeekTime = time64;
893        LOGV("VideoEditor3gpReader_jump VIDEO time us %ld ", time64);
894    } else {
895        LOGV("VideoEditor3gpReader_jump passed StreamHandler is not known\n");
896        return M4ERR_PARAMETER;
897    }
898    time64 = time64 / 1000; /* Convert the time into milli sec */
899    LOGV("VideoEditor3gpReader_jump time ms before seekset %ld ", time64);
900
901    M4OSA_INT64_TO_DOUBLE(timeDouble, time64);
902    *pTime = (M4OSA_Int32)timeDouble;
903
904    LOGV("VideoEditor3gpReader_jump end");
905    err = M4NO_ERROR;
906    return err;
907}
908/**
909********************************************************************************
910* @brief    reset the stream, that is seek it to beginning and make it ready
911* @note
912* @param    context:        (IN)    Context of the reader
913* @param    pStreamHandler  (IN)    The stream handler of the stream to reset
914* @return   M4NO_ERROR              there is no error
915* @return   M4ERR_PARAMETER         at least one parameter is not properly set
916********************************************************************************
917*/
918M4OSA_ERR VideoEditor3gpReader_reset(M4OSA_Context context,
919        M4_StreamHandler *pStreamHandler) {
920    VideoEditor3gpReader_Context* pC = (VideoEditor3gpReader_Context*)context;
921    M4OSA_ERR err = M4NO_ERROR;
922    M4SYS_StreamID streamIdArray[2];
923    M4SYS_AccessUnit* pAu;
924    M4OSA_Time time64;
925
926    M4OSA_DEBUG_IF1((pC == 0), M4ERR_PARAMETER,
927        "VideoEditor3gpReader_reset: invalid context");
928    M4OSA_DEBUG_IF1((pStreamHandler == 0), M4ERR_PARAMETER,
929        "VideoEditor3gpReader_reset: invalid pointer to M4_StreamHandler");
930
931    M4OSA_INT64_FROM_INT32(time64, 0);
932
933    LOGV("VideoEditor3gpReader_reset begin");
934
935    if (pStreamHandler == (M4_StreamHandler*)pC->mAudioStreamHandler) {
936        pAu = &pC->mAudioAu;
937    } else if (pStreamHandler == (M4_StreamHandler*)pC->mVideoStreamHandler) {
938        pAu = &pC->mVideoAu;
939    } else {
940        LOGV("VideoEditor3gpReader_reset passed StreamHandler is not known\n");
941        return M4ERR_PARAMETER;
942    }
943
944    pAu->CTS = time64;
945    pAu->DTS = time64;
946
947    LOGV("VideoEditor3gpReader_reset end");
948    return err;
949}
950
951/**
952********************************************************************************
953* @brief  Gets an access unit (AU) from the stream handler source.
954* @note   An AU is the smallest possible amount of data to be decoded by decoder
955*
956* @param    context:        (IN) Context of the reader
957* @param    pStreamHandler  (IN) The stream handler of the stream to make jump
958* @param    pAccessUnit     (IO) Pointer to access unit to fill with read data
959* @return   M4NO_ERROR           there is no error
960* @return   M4ERR_PARAMETER      at least one parameter is not properly set
961* @returns  M4ERR_ALLOC          memory allocation failed
962* @returns  M4WAR_NO_MORE_AU     there are no more access unit in the stream
963********************************************************************************
964*/
965M4OSA_ERR VideoEditor3gpReader_getNextAu(M4OSA_Context context,
966        M4_StreamHandler *pStreamHandler, M4_AccessUnit *pAccessUnit) {
967    VideoEditor3gpReader_Context* pC=(VideoEditor3gpReader_Context*)context;
968    M4OSA_ERR err = M4NO_ERROR;
969    M4SYS_AccessUnit* pAu;
970    int64_t tempTime64 = 0;
971    MediaBuffer *mMediaBuffer = NULL;
972    MediaSource::ReadOptions options;
973    M4OSA_Bool flag = M4OSA_FALSE;
974    status_t error;
975    int32_t i32Tmp = 0;
976
977    M4OSA_DEBUG_IF1((pReaderContext == 0), M4ERR_PARAMETER,
978        "VideoEditor3gpReader_getNextAu: invalid context");
979    M4OSA_DEBUG_IF1((pStreamHandler == 0), M4ERR_PARAMETER,
980        "VideoEditor3gpReader_getNextAu: invalid pointer to M4_StreamHandler");
981    M4OSA_DEBUG_IF1((pAccessUnit == 0),    M4ERR_PARAMETER,
982        "VideoEditor3gpReader_getNextAu: invalid pointer to M4_AccessUnit");
983
984    LOGV("VideoEditor3gpReader_getNextAu begin");
985
986    if (pStreamHandler == (M4_StreamHandler*)pC->mAudioStreamHandler) {
987        LOGV("VideoEditor3gpReader_getNextAu audio stream");
988        pAu = &pC->mAudioAu;
989        if (pC->mAudioSeeking == M4OSA_TRUE) {
990            LOGV("VideoEditor3gpReader_getNextAu audio seek time: %ld",
991                pC->mAudioSeekTime);
992            options.setSeekTo(pC->mAudioSeekTime);
993            pC->mAudioSource->read(&mMediaBuffer, &options);
994
995            mMediaBuffer->meta_data()->findInt64(kKeyTime,
996                (int64_t*)&tempTime64);
997            options.clearSeekTo();
998            pC->mAudioSeeking = M4OSA_FALSE;
999            flag = M4OSA_TRUE;
1000        } else {
1001            LOGV("VideoEditor3gpReader_getNextAu audio no seek:");
1002            pC->mAudioSource->read(&mMediaBuffer, &options);
1003            if (mMediaBuffer != NULL) {
1004                mMediaBuffer->meta_data()->findInt64(kKeyTime,
1005                    (int64_t*)&tempTime64);
1006            }
1007        }
1008    } else if (pStreamHandler == (M4_StreamHandler*)pC->mVideoStreamHandler) {
1009        LOGV("VideoEditor3gpReader_getNextAu video steram ");
1010        pAu = &pC->mVideoAu;
1011        if(pC->mVideoSeeking == M4OSA_TRUE) {
1012            flag = M4OSA_TRUE;
1013            LOGV("VideoEditor3gpReader_getNextAu seek: %ld",pC->mVideoSeekTime);
1014            options.setSeekTo(pC->mVideoSeekTime,
1015                MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC);
1016            do
1017            {
1018                if (mMediaBuffer != NULL) {
1019                    LOGV("VideoEditor3gpReader_getNextAu free the MediaBuffer");
1020                    mMediaBuffer->release();
1021                }
1022                error = pC->mVideoSource->read(&mMediaBuffer, &options);
1023                LOGV("VE3gpReader_getNextAu MediaBuffer %x , error %d",
1024                    mMediaBuffer, error);
1025                if (mMediaBuffer != NULL)
1026                {
1027                    if (mMediaBuffer->meta_data()->findInt32(kKeyIsSyncFrame,
1028                        &i32Tmp) && i32Tmp) {
1029                            LOGV("SYNC FRAME FOUND--%d", i32Tmp);
1030                        pAu->attribute = AU_RAP;
1031                    }
1032                    mMediaBuffer->meta_data()->findInt64(kKeyTime,
1033                        (int64_t*)&tempTime64);
1034                } else {
1035                    break;
1036                }
1037                options.clearSeekTo();
1038            } while(tempTime64 < pC->mVideoSeekTime);
1039
1040            LOGV("VE3gpReader_getNextAu: video  time with seek  = %lld:",
1041                tempTime64);
1042            pC->mVideoSeeking = M4OSA_FALSE;
1043        } else {
1044            LOGV("VideoEditor3gpReader_getNextAu video no seek:");
1045            pC->mVideoSource->read(&mMediaBuffer, &options);
1046
1047            if(mMediaBuffer != NULL) {
1048                if (mMediaBuffer->meta_data()->findInt32(kKeyIsSyncFrame,
1049                    &i32Tmp) && i32Tmp) {
1050                    LOGV("SYNC FRAME FOUND--%d", i32Tmp);
1051                    pAu->attribute = AU_RAP;
1052                }
1053                mMediaBuffer->meta_data()->findInt64(kKeyTime,
1054                    (int64_t*)&tempTime64);
1055                LOGV("VE3gpReader_getNextAu: video no seek time = %lld:",
1056                    tempTime64);
1057            }else {
1058                LOGV("VE3gpReader_getNextAu:video no seek time buffer is NULL");
1059            }
1060        }
1061    } else {
1062        LOGV("VideoEditor3gpReader_getNextAu M4ERR_PARAMETER");
1063        return M4ERR_PARAMETER;
1064    }
1065
1066    if (mMediaBuffer != NULL) {
1067        if( (pAu->dataAddress == NULL) ||  (pAu->size < \
1068            mMediaBuffer->range_length())) {
1069            if(pAu->dataAddress != NULL) {
1070                M4OSA_free((M4OSA_Int32*)pAu->dataAddress);
1071                pAu->dataAddress = NULL;
1072            }
1073            LOGV("Buffer lenght = %d ,%d",(mMediaBuffer->range_length() +\
1074                3) & ~0x3,(mMediaBuffer->range_length()));
1075
1076            pAu->dataAddress = (M4OSA_Int32*)M4OSA_malloc(
1077                (mMediaBuffer->range_length() + 3) & ~0x3,M4READER_3GP,
1078                    (M4OSA_Char*)"pAccessUnit->m_dataAddress" );
1079            if(pAu->dataAddress == NULL) {
1080                LOGV("VideoEditor3gpReader_getNextAu malloc failed");
1081                return M4ERR_ALLOC;
1082            }
1083        }
1084        pAu->size = mMediaBuffer->range_length();
1085
1086        memcpy((M4OSA_MemAddr8)pAu->dataAddress,
1087            (const char *)mMediaBuffer->data() + mMediaBuffer->range_offset(),
1088            mMediaBuffer->range_length());
1089
1090        if( (pStreamHandler == (M4_StreamHandler*)pC->mVideoStreamHandler)  &&
1091            (pStreamHandler->m_streamType == M4DA_StreamTypeVideoMpeg4Avc) ) {
1092            M4OSA_UInt32 size = mMediaBuffer->range_length();
1093            M4OSA_UInt8 *lbuffer;
1094
1095            lbuffer = (M4OSA_UInt8 *) pAu->dataAddress;
1096            LOGV("pAccessUnit->m_dataAddress size = %x",size);
1097
1098            lbuffer[0] = (size >> 24) & 0xFF;
1099            lbuffer[1] = (size >> 16) & 0xFF;
1100            lbuffer[2] = (size >> 8) & 0xFF;
1101            lbuffer[3] = (size) & 0xFF;
1102        }
1103
1104        pAu->CTS = tempTime64;
1105
1106        pAu->CTS = pAu->CTS / 1000; //converting the microsec to millisec
1107        LOGV("VideoEditor3gpReader_getNextAu CTS = %ld",pAu->CTS);
1108
1109        pAu->DTS  = pAu->CTS;
1110        if (pStreamHandler == (M4_StreamHandler*)pC->mAudioStreamHandler) {
1111            pAu->attribute = M4SYS_kFragAttrOk;
1112        }
1113        mMediaBuffer->release();
1114
1115        pAccessUnit->m_dataAddress = (M4OSA_Int8*) pAu->dataAddress;
1116        pAccessUnit->m_size = pAu->size;
1117        pAccessUnit->m_maxsize = pAu->size;
1118        pAccessUnit->m_CTS = pAu->CTS;
1119        pAccessUnit->m_DTS = pAu->DTS;
1120        pAccessUnit->m_attribute = pAu->attribute;
1121
1122    } else {
1123        LOGV("VideoEditor3gpReader_getNextAu: M4WAR_NO_MORE_AU (EOS) reached");
1124        pAccessUnit->m_size = 0;
1125        err = M4WAR_NO_MORE_AU;
1126    }
1127    options.clearSeekTo();
1128
1129    pAu->nbFrag = 0;
1130    mMediaBuffer = NULL;
1131    LOGV("VideoEditor3gpReader_getNextAu end ");
1132
1133    return err;
1134}
1135/**
1136 *******************************************************************************
1137 * @brief   Split the AVC DSI in its different components and write it in
1138 *          ONE memory buffer
1139 * @note
1140 * @param   pStreamHandler:         (IN/OUT) The MPEG4-AVC stream
1141 * @param   pDecoderConfigLocal:    (IN) The DSI buffer
1142 * @param   decoderConfigSizeLocal: (IN) The DSI buffer size
1143 * @return  M4NO_ERROR              there is no error
1144 * @return  ERR_FILE_SYNTAX_ERROR   pDecoderConfigLocal is NULL
1145 *******************************************************************************
1146*/
1147static M4OSA_ERR VideoEditor3gpReader_AnalyseAvcDsi(
1148        M4_StreamHandler *pStreamHandler, M4OSA_Int32* pDecoderConfigLocal,
1149        M4OSA_Int32 decoderConfigSizeLocal) {
1150    struct _avcSpecificInfo *pAvcSpecInfo = M4OSA_NULL;
1151    M4OSA_UInt32 uiSpecInfoSize;
1152    M4OSA_Context pBitParserContext = M4OSA_NULL;
1153    M4OSA_MemAddr8 pPos;
1154
1155    /**
1156     * First parsing to get the total allocation size (we must not do
1157     * multiple malloc, but only one instead) */
1158    {
1159        M4OSA_Int32 val;
1160        M4OSA_UInt32 i,j;
1161        M4OSA_UInt8 nalUnitLength;
1162        M4OSA_UInt8  numOfSequenceParameterSets;
1163        M4OSA_UInt32 uiTotalSizeOfSPS = 0;
1164        M4OSA_UInt8  numOfPictureParameterSets;
1165        M4OSA_UInt32 uiTotalSizeOfPPS = 0;
1166        M4OSA_UInt32 uiSize;
1167        struct _avcSpecificInfo avcSpIf;
1168
1169        avcSpIf.m_nalUnitLength = 0;
1170
1171        if (M4OSA_NULL == pDecoderConfigLocal) {
1172            return M4ERR_READER3GP_DECODER_CONFIG_ERROR;
1173        }
1174
1175        VideoEditor3gpReader_MPEG4BitStreamParserInit(&pBitParserContext,
1176            pDecoderConfigLocal, decoderConfigSizeLocal);
1177
1178        if (M4OSA_NULL == pBitParserContext) {
1179            return M4ERR_ALLOC;
1180        }
1181
1182        VideoEditor3gpReader_BitStreamParserFlushBits(pBitParserContext, 8);
1183                                       /* 8 bits -- configuration version */
1184        VideoEditor3gpReader_BitStreamParserFlushBits(pBitParserContext, 8);
1185                                       /* 8 bits -- avc profile indication*/
1186        VideoEditor3gpReader_BitStreamParserFlushBits(pBitParserContext, 8);
1187                                       /* 8 bits -- profile compatibility */
1188        VideoEditor3gpReader_BitStreamParserFlushBits(pBitParserContext, 8);
1189                                       /* 8 bits -- avc level indication*/
1190        val=VideoEditor3gpReader_BitStreamParserShowBits(pBitParserContext, 8);
1191                       /* 6 bits reserved 111111b 2 bits length Size minus one*/
1192        VideoEditor3gpReader_BitStreamParserFlushBits(pBitParserContext, 8);
1193                                       /* m_nalUnitLength */
1194
1195        nalUnitLength = (M4OSA_UInt8)((val & 0x03) + 1);/*0b11111100*/
1196        if (nalUnitLength > 4) {
1197            pStreamHandler->m_decoderSpecificInfoSize = 0;
1198            pStreamHandler->m_pDecoderSpecificInfo = M4OSA_NULL;
1199            VideoEditor3gpReader_BitStreamParserCleanUp(pBitParserContext);
1200        } else {
1201            /**
1202             * SPS table */
1203            val=VideoEditor3gpReader_BitStreamParserShowBits(pBitParserContext,
1204            8);/* 3 bits-reserved 111b-5 bits number of sequence parameter set*/
1205            numOfSequenceParameterSets = val & 0x1F;
1206            /*1F instead of E0*/ /*0b11100000*/ /*Number of seq parameter sets*/
1207            VideoEditor3gpReader_BitStreamParserFlushBits(pBitParserContext, 8);
1208            for (i=0; i < numOfSequenceParameterSets; i++) {
1209                /**
1210                 * Get the size of this element */
1211                uiSize =
1212                    (M4OSA_UInt32)VideoEditor3gpReader_BitStreamParserShowBits(
1213                    pBitParserContext, 16);
1214                uiTotalSizeOfSPS += uiSize;
1215                VideoEditor3gpReader_BitStreamParserFlushBits(
1216                    pBitParserContext, 16);
1217                /**
1218                 *Read the element(dont keep it, we only want size right now) */
1219                for (j=0; j<uiSize; j++) {
1220                    VideoEditor3gpReader_BitStreamParserFlushBits(
1221                        pBitParserContext, 8);
1222                }
1223            }
1224
1225            /**
1226             * SPS table */
1227            numOfPictureParameterSets=(M4OSA_UInt8)\
1228                VideoEditor3gpReader_BitStreamParserShowBits(pBitParserContext,
1229                    8);
1230            VideoEditor3gpReader_BitStreamParserFlushBits(pBitParserContext, 8);
1231            for (i=0; i < numOfPictureParameterSets; i++) {
1232                /**
1233                 * Get the size of this element */
1234                uiSize = (M4OSA_UInt32)
1235                    VideoEditor3gpReader_BitStreamParserShowBits(
1236                    pBitParserContext, 16);
1237                uiTotalSizeOfPPS += uiSize;
1238                VideoEditor3gpReader_BitStreamParserFlushBits(
1239                    pBitParserContext, 16);
1240                /**
1241                 *Read the element(dont keep it,we only want size right now)*/
1242                for (j=0; j<uiSize; j++) {
1243                    VideoEditor3gpReader_BitStreamParserFlushBits(
1244                        pBitParserContext, 8);
1245                }
1246            }
1247
1248            /**
1249             * Compute the size of the full buffer */
1250            uiSpecInfoSize = sizeof(struct _avcSpecificInfo) +
1251                     numOfSequenceParameterSets * sizeof(struct _parameterSet)
1252                     + /**< size of the table of SPS elements */
1253                     numOfPictureParameterSets  * sizeof(struct _parameterSet)
1254                     + /**< size of the table of PPS elements */
1255                     uiTotalSizeOfSPS +
1256                     uiTotalSizeOfPPS;
1257            /**
1258             * Allocate the buffer */
1259            pAvcSpecInfo =(struct _avcSpecificInfo*)M4OSA_malloc(uiSpecInfoSize,
1260                M4READER_3GP, (M4OSA_Char*)"MPEG-4 AVC DecoderSpecific");
1261            if (M4OSA_NULL == pAvcSpecInfo) {
1262                VideoEditor3gpReader_BitStreamParserCleanUp(pBitParserContext);
1263                return M4ERR_ALLOC;
1264            }
1265
1266            /**
1267             * Set the pointers to the correct part of the buffer */
1268            pAvcSpecInfo->m_nalUnitLength = nalUnitLength;
1269            pAvcSpecInfo->m_numOfSequenceParameterSets =
1270                numOfSequenceParameterSets;
1271            pAvcSpecInfo->m_numOfPictureParameterSets  =
1272                numOfPictureParameterSets;
1273
1274            /* We place the SPS param sets table after m_pPictureParameterSet */
1275            pAvcSpecInfo->m_pSequenceParameterSet= (struct _parameterSet*)(
1276                (M4OSA_MemAddr8)(&pAvcSpecInfo->m_pPictureParameterSet) +
1277                sizeof(pAvcSpecInfo->m_pPictureParameterSet));
1278            /*We place the PPS param sets table after the SPS param sets table*/
1279            pAvcSpecInfo->m_pPictureParameterSet = (struct _parameterSet*)(
1280                (M4OSA_MemAddr8)(pAvcSpecInfo->m_pSequenceParameterSet) +
1281                (numOfSequenceParameterSets * sizeof(struct _parameterSet)));
1282            /**< The data will be placed after the PPS param sets table */
1283            pPos = (M4OSA_MemAddr8)pAvcSpecInfo->m_pPictureParameterSet +
1284                (numOfPictureParameterSets * sizeof(struct _parameterSet));
1285
1286            /**
1287             * reset the bit parser */
1288            VideoEditor3gpReader_BitStreamParserCleanUp(pBitParserContext);
1289        }
1290    }
1291
1292    /**
1293     * Second parsing to copy the data */
1294    if (M4OSA_NULL != pAvcSpecInfo) {
1295        M4OSA_Int32 i,j;
1296
1297        VideoEditor3gpReader_MPEG4BitStreamParserInit(&pBitParserContext,
1298            pDecoderConfigLocal, decoderConfigSizeLocal);
1299
1300        if (M4OSA_NULL == pBitParserContext) {
1301            M4OSA_free((M4OSA_MemAddr32)pAvcSpecInfo);
1302            return M4ERR_ALLOC;
1303        }
1304
1305        VideoEditor3gpReader_BitStreamParserFlushBits(pBitParserContext, 8);
1306            /* 8 bits -- configuration version */
1307        VideoEditor3gpReader_BitStreamParserFlushBits(pBitParserContext, 8);
1308            /* 8 bits -- avc profile indication*/
1309        VideoEditor3gpReader_BitStreamParserFlushBits(pBitParserContext, 8);
1310            /* 8 bits -- profile compatibility */
1311        VideoEditor3gpReader_BitStreamParserFlushBits(pBitParserContext, 8);
1312            /* 8 bits -- avc level indication*/
1313        VideoEditor3gpReader_BitStreamParserFlushBits(pBitParserContext, 8);
1314            /* m_nalUnitLength */
1315        VideoEditor3gpReader_BitStreamParserFlushBits(pBitParserContext, 8);
1316        /* 3 bits -- reserved 111b -- 5 bits number of sequence parameter set*/
1317
1318        for (i=0; i < pAvcSpecInfo->m_numOfSequenceParameterSets; i++) {
1319            pAvcSpecInfo->m_pSequenceParameterSet[i].m_length =
1320                (M4OSA_UInt16)VideoEditor3gpReader_BitStreamParserShowBits(
1321                pBitParserContext, 16);
1322            VideoEditor3gpReader_BitStreamParserFlushBits(pBitParserContext,16);
1323
1324            pAvcSpecInfo->m_pSequenceParameterSet[i].m_pParameterSetUnit =
1325                (M4OSA_UInt8*)pPos;  /**< current position in the buffer */
1326            pPos += pAvcSpecInfo->m_pSequenceParameterSet[i].m_length;
1327                /**< increment the position in the buffer */
1328            for (j=0; j<pAvcSpecInfo->m_pSequenceParameterSet[i].m_length;j++){
1329                pAvcSpecInfo->m_pSequenceParameterSet[i].m_pParameterSetUnit[j]=
1330                    (M4OSA_UInt8)VideoEditor3gpReader_BitStreamParserShowBits(
1331                    pBitParserContext, 8);
1332                VideoEditor3gpReader_BitStreamParserFlushBits(
1333                    pBitParserContext, 8);
1334            }
1335        }
1336
1337        VideoEditor3gpReader_BitStreamParserFlushBits(pBitParserContext, 8);
1338            /* number of pîcture parameter set*/
1339
1340        for (i=0; i < pAvcSpecInfo->m_numOfPictureParameterSets; i++) {
1341            pAvcSpecInfo->m_pPictureParameterSet[i].m_length =
1342                (M4OSA_UInt16)VideoEditor3gpReader_BitStreamParserShowBits(
1343                pBitParserContext, 16);
1344            VideoEditor3gpReader_BitStreamParserFlushBits(pBitParserContext,16);
1345
1346            pAvcSpecInfo->m_pPictureParameterSet[i].m_pParameterSetUnit =
1347                (M4OSA_UInt8*)pPos;   /**< current position in the buffer */
1348            pPos += pAvcSpecInfo->m_pPictureParameterSet[i].m_length;
1349                /**< increment the position in the buffer */
1350            for (j=0; j<pAvcSpecInfo->m_pPictureParameterSet[i].m_length; j++) {
1351                pAvcSpecInfo->m_pPictureParameterSet[i].m_pParameterSetUnit[j] =
1352                    (M4OSA_UInt8)VideoEditor3gpReader_BitStreamParserShowBits(
1353                    pBitParserContext, 8);
1354                VideoEditor3gpReader_BitStreamParserFlushBits(
1355                    pBitParserContext, 8);
1356            }
1357        }
1358        VideoEditor3gpReader_BitStreamParserCleanUp(pBitParserContext);
1359        pStreamHandler->m_decoderSpecificInfoSize = uiSpecInfoSize;
1360        pStreamHandler->m_pDecoderSpecificInfo = (M4OSA_UInt8*)pAvcSpecInfo;
1361    }
1362    pStreamHandler->m_H264decoderSpecificInfoSize  =  decoderConfigSizeLocal;
1363    pStreamHandler->m_pH264DecoderSpecificInfo  = (M4OSA_UInt8*)M4OSA_malloc(
1364        decoderConfigSizeLocal, M4READER_3GP,
1365        (M4OSA_Char*)"MPEG-4 AVC DecoderSpecific");
1366    if (M4OSA_NULL == pStreamHandler->m_pH264DecoderSpecificInfo) {
1367        goto cleanup;
1368    }
1369
1370    M4OSA_memcpy((M4OSA_MemAddr8 ) pStreamHandler->m_pH264DecoderSpecificInfo,
1371        (M4OSA_MemAddr8 )pDecoderConfigLocal,
1372        pStreamHandler->m_H264decoderSpecificInfoSize);
1373    return M4NO_ERROR;
1374cleanup:
1375    VideoEditor3gpReader_BitStreamParserCleanUp(pBitParserContext);
1376    return M4ERR_READER3GP_DECODER_CONFIG_ERROR;
1377}
1378/**
1379********************************************************************************
1380* @brief    Get the next stream found in the 3gp file
1381* @note
1382* @param    context:     (IN)    Context of the reader
1383* @param    pMediaFamily: OUT)   pointer to a user allocated
1384*                                M4READER_MediaFamily that will be filled
1385*                                with the media family of the found stream
1386* @param    pStreamHandler:(OUT) pointer to StreamHandler that will be allocated
1387*                                and filled with the found stream description
1388* @return   M4NO_ERROR              there is no error
1389* @return   M4ERR_BAD_CONTEXT       provided context is not a valid one
1390* @return   M4ERR_PARAMETER         at least one parameter is not properly set
1391* @return   M4WAR_NO_MORE_STREAM    no more available stream in the media
1392********************************************************************************
1393*/
1394M4OSA_ERR VideoEditor3gpReader_getNextStreamHandler(M4OSA_Context context,
1395        M4READER_MediaFamily *pMediaFamily,
1396        M4_StreamHandler **pStreamHandler) {
1397    VideoEditor3gpReader_Context* pC=(VideoEditor3gpReader_Context*)context;
1398    M4OSA_ERR err = M4NO_ERROR;
1399    M4SYS_StreamID streamIdArray[2];
1400    M4SYS_StreamDescription streamDesc;
1401    M4_AudioStreamHandler* pAudioStreamHandler;
1402    M4_VideoStreamHandler* pVideoStreamHandler;
1403    M4OSA_Int8 *DecoderSpecificInfo = M4OSA_NULL;
1404    M4OSA_Int32 decoderSpecificInfoSize =0, maxAUSize = 0;
1405
1406    M4_StreamType streamType = M4DA_StreamTypeUnknown;
1407    M4OSA_UInt8 temp, i, trackCount;
1408    M4OSA_Bool haveAudio = M4OSA_FALSE;
1409    M4OSA_Bool haveVideo = M4OSA_FALSE;
1410    sp<MetaData> meta  = NULL;
1411    int64_t Duration = 0;
1412    M4OSA_UInt8* DecoderSpecific = M4OSA_NULL ;
1413    uint32_t type;
1414    const void *data;
1415    size_t size;
1416    const void *codec_specific_data;
1417    size_t codec_specific_data_size;
1418    M4OSA_Int32  ptempTime;
1419
1420    LOGV("VideoEditor3gpReader_getNextStreamHandler begin");
1421
1422    M4OSA_DEBUG_IF1((pC == 0), M4ERR_PARAMETER,
1423        "VideoEditor3gpReader_getNextStreamHandler: invalid context");
1424    M4OSA_DEBUG_IF1((pMediaFamily   == 0), M4ERR_PARAMETER,
1425        "getNextStreamHandler: invalid pointer to MediaFamily");
1426    M4OSA_DEBUG_IF1((pStreamHandler == 0), M4ERR_PARAMETER,
1427        "getNextStreamHandler: invalid pointer to StreamHandler");
1428
1429    trackCount = pC->mExtractor->countTracks();
1430    temp = pC->mCurrTrack;
1431
1432    if(temp >= trackCount) {
1433        LOGV("VideoEditor3gpReader_getNextStreamHandler error = %d",
1434            M4WAR_NO_MORE_STREAM);
1435        return (M4WAR_NO_MORE_STREAM);
1436    } else {
1437        const char *mime;
1438        meta = pC->mExtractor->getTrackMetaData(temp);
1439        CHECK(meta->findCString(kKeyMIMEType, &mime));
1440
1441        if (!haveVideo && !strncasecmp(mime, "video/", 6)) {
1442            pC->mVideoSource = pC->mExtractor->getTrack(temp);
1443            pC->mVideoSource->start();
1444
1445            *pMediaFamily = M4READER_kMediaFamilyVideo;
1446            haveVideo = true;
1447            LOGV("VideoEditor3gpReader_getNextStreamHandler getTrack called");
1448            if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
1449                streamType = M4DA_StreamTypeVideoMpeg4Avc;
1450            } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_H263)) {
1451                streamType = M4DA_StreamTypeVideoH263;
1452            } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4)) {
1453                streamType = M4DA_StreamTypeVideoMpeg4;
1454            } else {
1455                LOGV("VideoEditor3gpReaderGetNextStreamHandler streamTypeNONE");
1456            }
1457            LOGV("VideoEditor3gpReader_getNextStreamHandler: stream type: %d ",
1458                streamType);
1459
1460            if(streamType != M4DA_StreamTypeUnknown) {
1461                pC->mStreamType = streamType;
1462                pC->mStreamId = pC->mCurrTrack;
1463
1464                pVideoStreamHandler = (M4_VideoStreamHandler*)M4OSA_malloc
1465                    (sizeof(M4_VideoStreamHandler), M4READER_3GP,
1466                    (M4OSA_Char*)"M4_VideoStreamHandler");
1467                if (M4OSA_NULL == pVideoStreamHandler) {
1468                    return M4ERR_ALLOC;
1469                }
1470                pVideoStreamHandler->m_structSize=sizeof(M4_VideoStreamHandler);
1471
1472                meta->findInt32(kKeyWidth,
1473                    (int32_t*)&(pVideoStreamHandler->m_videoWidth));
1474                meta->findInt32(kKeyHeight,
1475                    (int32_t*)&(pVideoStreamHandler->m_videoHeight));
1476
1477                (*pStreamHandler)  = (M4_StreamHandler*)(pVideoStreamHandler);
1478                meta->findInt64(kKeyDuration,
1479                    (int64_t*)&(Duration));
1480                ((*pStreamHandler)->m_duration) =
1481                    (int32_t)((Duration)/1000); // conversion to mS
1482                pC->mMaxDuration = ((*pStreamHandler)->m_duration);
1483                LOGV("VideoEditor3gpReader_getNextStreamHandler m_duration %d",
1484                    (*pStreamHandler)->m_duration);
1485
1486                pC->mFileSize  = 0;
1487
1488                meta->findInt32(kKeyMaxInputSize, (int32_t*)&(maxAUSize));
1489                if(maxAUSize == 0) {
1490                    maxAUSize = 70000;
1491                }
1492                (*pStreamHandler)->m_maxAUSize = maxAUSize;
1493                LOGV("<<<<<<<<<<   video: mMaxAUSize from MP4 extractor: %d",
1494                    (*pStreamHandler)->m_maxAUSize);
1495
1496                //check this
1497                pVideoStreamHandler->m_averageFrameRate = 15;
1498                if( (M4DA_StreamTypeVideoH263       == streamType) ||
1499                    (M4DA_StreamTypeVideoMpeg4Avc   == streamType)){
1500                    ((M4_StreamHandler*)pVideoStreamHandler)->m_averageBitRate =
1501                        384000;
1502                }
1503                pC->mVideoStreamHandler =
1504                    (M4_StreamHandler*)(pVideoStreamHandler);
1505
1506                /* Get the DSI info */
1507                if(M4DA_StreamTypeVideoH263 == streamType) {
1508                    if (meta->findData(kKeyESDS, &type, &data, &size)) {
1509                        ESDS esds((const char *)data, size);
1510                        CHECK_EQ(esds.InitCheck(), OK);
1511
1512                        esds.getCodecSpecificInfo(
1513                            &codec_specific_data, &codec_specific_data_size);
1514                        (*pStreamHandler)->m_decoderSpecificInfoSize =
1515                            codec_specific_data_size;
1516                        if ((*pStreamHandler)->m_decoderSpecificInfoSize != 0) {
1517                            DecoderSpecific = (M4OSA_UInt8*)M4OSA_malloc(
1518                                (*pStreamHandler)->m_decoderSpecificInfoSize,
1519                                M4READER_3GP,(M4OSA_Char*)"H263 DSI");
1520                            if (M4OSA_NULL == DecoderSpecific) {
1521                                return M4ERR_ALLOC;
1522                            }
1523                            M4OSA_memcpy((M4OSA_MemAddr8)DecoderSpecific,
1524                                (M4OSA_MemAddr8)codec_specific_data,
1525                                codec_specific_data_size);
1526                            (*pStreamHandler)->m_pDecoderSpecificInfo =
1527                                DecoderSpecific;
1528                        }
1529                        else {
1530                            (*pStreamHandler)->m_pDecoderSpecificInfo =
1531                                M4OSA_NULL;
1532                        }
1533                    } else {
1534                        LOGV("VE_getNextStreamHandler: H263 dsi not found");
1535                        (*pStreamHandler)->m_pDecoderSpecificInfo = M4OSA_NULL;
1536                        (*pStreamHandler)->m_decoderSpecificInfoSize = 0;
1537                        (*pStreamHandler)->m_H264decoderSpecificInfoSize = 0;
1538                        (*pStreamHandler)->m_pH264DecoderSpecificInfo =
1539                            M4OSA_NULL;
1540                        (*pStreamHandler)->m_pESDSInfo = M4OSA_NULL;
1541                        (*pStreamHandler)->m_ESDSInfoSize = 0;
1542                    }
1543                }
1544                else if(M4DA_StreamTypeVideoMpeg4Avc == streamType) {
1545                    if(meta->findData(kKeyAVCC, &type, &data, &size)) {
1546                        decoderSpecificInfoSize = size;
1547                        if (decoderSpecificInfoSize != 0) {
1548                            DecoderSpecificInfo = (M4OSA_Int8*)M4OSA_malloc(
1549                                decoderSpecificInfoSize, M4READER_3GP,
1550                                (M4OSA_Char*)"H264 DecoderSpecific" );
1551                            if (M4OSA_NULL == DecoderSpecificInfo) {
1552                                LOGV("VideoEditor3gp_getNextStream is NULL ");
1553                                return M4ERR_ALLOC;
1554                            }
1555                            M4OSA_memcpy((M4OSA_MemAddr8)DecoderSpecificInfo,
1556                                (M4OSA_MemAddr8)data, decoderSpecificInfoSize);
1557                        } else {
1558                            LOGV("DSI Size %d", decoderSpecificInfoSize);
1559                            DecoderSpecificInfo = M4OSA_NULL;
1560                        }
1561                    }
1562                    (*pStreamHandler)->m_pESDSInfo = M4OSA_NULL;
1563                    (*pStreamHandler)->m_ESDSInfoSize = 0;
1564
1565                    err = VideoEditor3gpReader_AnalyseAvcDsi(*pStreamHandler,
1566                    (M4OSA_Int32*)DecoderSpecificInfo, decoderSpecificInfoSize);
1567
1568                    if (M4NO_ERROR != err) {
1569                        return err;
1570                    }
1571                    LOGV("decsize %d, h264decsize %d: %d", (*pStreamHandler)->\
1572                        m_decoderSpecificInfoSize, (*pStreamHandler)->\
1573                        m_H264decoderSpecificInfoSize);
1574
1575                    if(M4OSA_NULL != DecoderSpecificInfo) {
1576                        M4OSA_free((M4OSA_MemAddr32)DecoderSpecificInfo);
1577                        DecoderSpecificInfo = M4OSA_NULL;
1578                    }
1579                } else if( (M4DA_StreamTypeVideoMpeg4 == streamType) ) {
1580                    if (meta->findData(kKeyESDS, &type, &data, &size)) {
1581                        ESDS esds((const char *)data, size);
1582                        CHECK_EQ(esds.InitCheck(), OK);
1583
1584                        (*pStreamHandler)->m_ESDSInfoSize = size;
1585                        (*pStreamHandler)->m_pESDSInfo = (M4OSA_UInt8*)\
1586                        M4OSA_malloc((*pStreamHandler)->m_ESDSInfoSize,
1587                        M4READER_3GP, (M4OSA_Char*)"H263 DecoderSpecific" );
1588                        if (M4OSA_NULL == (*pStreamHandler)->m_pESDSInfo) {
1589                            return M4ERR_ALLOC;
1590                        }
1591                        M4OSA_memcpy((M4OSA_MemAddr8)(*pStreamHandler)->\
1592                            m_pESDSInfo, (M4OSA_MemAddr8)data, size);
1593
1594                        esds.getCodecSpecificInfo(&codec_specific_data,
1595                            &codec_specific_data_size);
1596                        LOGV("VE MP4 dsisize: %d, %x", codec_specific_data_size,
1597                            codec_specific_data);
1598
1599                        (*pStreamHandler)->m_decoderSpecificInfoSize =
1600                            codec_specific_data_size;
1601                        if ((*pStreamHandler)->m_decoderSpecificInfoSize != 0) {
1602                            DecoderSpecific = (M4OSA_UInt8*)M4OSA_malloc(
1603                                (*pStreamHandler)->m_decoderSpecificInfoSize,
1604                                M4READER_3GP, (M4OSA_Char*)" DecoderSpecific" );
1605                            if (M4OSA_NULL == DecoderSpecific) {
1606                                return M4ERR_ALLOC;
1607                            }
1608                            M4OSA_memcpy((M4OSA_MemAddr8)DecoderSpecific,
1609                                (M4OSA_MemAddr8)codec_specific_data,
1610                                codec_specific_data_size);
1611                            (*pStreamHandler)->m_pDecoderSpecificInfo =
1612                                DecoderSpecific;
1613                        }
1614                        else {
1615                            (*pStreamHandler)->m_pDecoderSpecificInfo =
1616                                M4OSA_NULL;
1617                        }
1618                        (*pStreamHandler)->m_pH264DecoderSpecificInfo =
1619                            M4OSA_NULL;
1620                        (*pStreamHandler)->m_H264decoderSpecificInfoSize = 0;
1621                    }
1622                } else {
1623                    LOGV("VideoEditor3gpReader_getNextStream NO video stream");
1624                    return M4ERR_READER_UNKNOWN_STREAM_TYPE;
1625                }
1626            }
1627            else {
1628                LOGV("VideoEditor3gpReader_getNextStream NO video stream");
1629                return M4ERR_READER_UNKNOWN_STREAM_TYPE;
1630            }
1631
1632        } else if (!haveAudio && !strncasecmp(mime, "audio/", 6)) {
1633            LOGV("VideoEditor3gpReader_getNextStream audio getTrack called");
1634            pC->mAudioSource = pC->mExtractor->getTrack(pC->mCurrTrack);
1635            pC->mAudioSource->start();
1636            *pMediaFamily = M4READER_kMediaFamilyAudio;
1637
1638            if(!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_NB)) {
1639                streamType = M4DA_StreamTypeAudioAmrNarrowBand;
1640            } else if(!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_WB)) {
1641                streamType = M4DA_StreamTypeAudioAmrWideBand;
1642            }
1643            else if(!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
1644                streamType = M4DA_StreamTypeAudioAac;
1645            } else {
1646                LOGV("VideoEditor3gpReader_getNextStrea streamtype Unknown ");
1647            }
1648            if(streamType != M4DA_StreamTypeUnknown) {
1649                pC->mStreamType = streamType;
1650                pC->mStreamId = pC->mCurrTrack;
1651
1652                LOGV("VE streamtype %d ,id %d",  streamType, pC->mCurrTrack);
1653
1654                pAudioStreamHandler = (M4_AudioStreamHandler*)M4OSA_malloc
1655                    (sizeof(M4_AudioStreamHandler), M4READER_3GP,
1656                    (M4OSA_Char*)"M4_AudioStreamHandler");
1657                if (M4OSA_NULL == pAudioStreamHandler) {
1658                    return M4ERR_ALLOC;
1659                }
1660                pAudioStreamHandler->m_structSize=sizeof(M4_AudioStreamHandler);
1661                pAudioStreamHandler->m_byteSampleSize   = 0;
1662                pAudioStreamHandler->m_nbChannels       = 0;
1663                pAudioStreamHandler->m_samplingFrequency= 0;
1664                pAudioStreamHandler->m_byteFrameLength  = 0;
1665
1666                (*pStreamHandler) = (M4_StreamHandler*)(pAudioStreamHandler);
1667                pC->mAudioStreamHandler =
1668                    (M4_StreamHandler*)(pAudioStreamHandler);
1669                (*pStreamHandler)->m_averageBitRate = 0;
1670                haveAudio = true;
1671                pC->mAudioStreamHandler=(M4_StreamHandler*)pAudioStreamHandler;
1672                pC->mAudioStreamHandler->m_pESDSInfo = M4OSA_NULL;
1673                pC->mAudioStreamHandler->m_ESDSInfoSize = 0;
1674
1675                meta->findInt32(kKeyMaxInputSize, (int32_t*)&(maxAUSize));
1676                if(maxAUSize == 0) {
1677                    maxAUSize = 70000;
1678                }
1679                (*pStreamHandler)->m_maxAUSize = maxAUSize;
1680                LOGV("VE Audio mMaxAUSize from MP4 extractor: %d", maxAUSize);
1681            }
1682            if((M4DA_StreamTypeAudioAmrNarrowBand == streamType) ||
1683                (M4DA_StreamTypeAudioAmrWideBand == streamType)) {
1684                M4OSA_UInt32 freqIndex = 0; /**< AMR NB */
1685                M4OSA_UInt32 modeSet;
1686                M4OSA_UInt32 i;
1687                M4OSA_Context pBitParserContext = M4OSA_NULL;
1688
1689                if(M4DA_StreamTypeAudioAmrWideBand == streamType) {
1690                    freqIndex = 1; /**< AMR WB */
1691                }
1692
1693                if (meta->findData(kKeyESDS, &type, &data, &size)) {
1694                    ESDS esds((const char *)data, size);
1695                    CHECK_EQ(esds.InitCheck(), OK);
1696
1697                    esds.getCodecSpecificInfo(&codec_specific_data,
1698                        &codec_specific_data_size);
1699                    (*pStreamHandler)->m_decoderSpecificInfoSize =
1700                        codec_specific_data_size;
1701
1702                    if ((*pStreamHandler)->m_decoderSpecificInfoSize != 0) {
1703                        DecoderSpecific = (M4OSA_UInt8*)M4OSA_malloc(
1704                            (*pStreamHandler)->m_decoderSpecificInfoSize,
1705                            M4READER_3GP, (M4OSA_Char*)"H263 DecoderSpecific" );
1706                        if (M4OSA_NULL == DecoderSpecific) {
1707                            return M4ERR_ALLOC;
1708                        }
1709                        M4OSA_memcpy((M4OSA_MemAddr8)DecoderSpecific,
1710                            (M4OSA_MemAddr8)codec_specific_data,
1711                            codec_specific_data_size);
1712                        (*pStreamHandler)->m_pDecoderSpecificInfo =
1713                            DecoderSpecific;
1714                    } else {
1715                        (*pStreamHandler)->m_pDecoderSpecificInfo = M4OSA_NULL;
1716                    }
1717                } else {
1718                    M4OSA_UChar AmrDsi[] =
1719                        {'P','H','L','P',0x00, 0x00, 0x80, 0x00, 0x01,};
1720                    (*pStreamHandler)->m_decoderSpecificInfoSize = 9;
1721                    DecoderSpecific = (M4OSA_UInt8*)M4OSA_malloc(
1722                        (*pStreamHandler)->m_decoderSpecificInfoSize,
1723                        M4READER_3GP, (M4OSA_Char*)"H263 DecoderSpecific" );
1724                    if (M4OSA_NULL == DecoderSpecific) {
1725                        return M4ERR_ALLOC;
1726                    }
1727                    if(freqIndex ==0) {
1728                        AmrDsi[8] = 0x01;
1729                    } else {
1730                        AmrDsi[8] = 0x02;
1731                    }
1732                    for(i = 0; i< 9; i++) {
1733                        DecoderSpecific[i] = AmrDsi[i];
1734                    }
1735                    (*pStreamHandler)->m_pDecoderSpecificInfo = DecoderSpecific;
1736                }
1737                (*pStreamHandler)->m_averageBitRate =
1738                    VideoEditor3gpReader_AmrBitRate[freqIndex][7];
1739            } else if((M4DA_StreamTypeAudioAac == streamType)) {
1740                if (meta->findData(kKeyESDS, &type, &data, &size)) {
1741                    ESDS esds((const char *)data, size);
1742                    CHECK_EQ(esds.InitCheck(), OK);
1743
1744                    (*pStreamHandler)->m_ESDSInfoSize = size;
1745                    (*pStreamHandler)->m_pESDSInfo = (M4OSA_UInt8*)M4OSA_malloc(
1746                        (*pStreamHandler)->m_ESDSInfoSize, M4READER_3GP,
1747                        (M4OSA_Char*)"H263 DecoderSpecific" );
1748                    if (M4OSA_NULL == (*pStreamHandler)->m_pESDSInfo) {
1749                        return M4ERR_ALLOC;
1750                    }
1751                    M4OSA_memcpy((M4OSA_MemAddr8)(*pStreamHandler)->m_pESDSInfo,
1752                    (M4OSA_MemAddr8)data, size);
1753                    esds.getCodecSpecificInfo(&codec_specific_data,
1754                        &codec_specific_data_size);
1755
1756                    LOGV("VEdsi %d,%x",codec_specific_data_size,
1757                        codec_specific_data);
1758
1759                    (*pStreamHandler)->m_decoderSpecificInfoSize =
1760                        codec_specific_data_size;
1761                    if ((*pStreamHandler)->m_decoderSpecificInfoSize != 0) {
1762                        DecoderSpecific = (M4OSA_UInt8*)M4OSA_malloc(
1763                            (*pStreamHandler)->m_decoderSpecificInfoSize,
1764                            M4READER_3GP, (M4OSA_Char*)"H263 DecoderSpecific" );
1765                        if (M4OSA_NULL == DecoderSpecific) {
1766                            return M4ERR_ALLOC;
1767                        }
1768                        M4OSA_memcpy((M4OSA_MemAddr8)DecoderSpecific,
1769                            (M4OSA_MemAddr8)codec_specific_data,
1770                            codec_specific_data_size);
1771                        (*pStreamHandler)->m_pDecoderSpecificInfo =
1772                            DecoderSpecific;
1773                    } else {
1774                        (*pStreamHandler)->m_pDecoderSpecificInfo = M4OSA_NULL;
1775                    }
1776                }
1777            } else {
1778                LOGV("VideoEditor3gpReader_getNextStream mStreamType: none ");
1779                return M4ERR_READER_UNKNOWN_STREAM_TYPE;
1780            }
1781        } else {
1782            LOGV("VE noaudio-video stream:pC->mCurrTrack = %d ",pC->mCurrTrack);
1783            pC->mCurrTrack++; //Increment current track to get the next track
1784            return M4ERR_READER_UNKNOWN_STREAM_TYPE;
1785        }
1786        LOGV("VE StreamType: %d, stremhandler %x",streamType, *pStreamHandler );
1787        (*pStreamHandler)->m_streamType = streamType;
1788        (*pStreamHandler)->m_streamId   = pC->mStreamId;
1789        (*pStreamHandler)->m_pUserData  = M4OSA_NULL;
1790        (*pStreamHandler)->m_structSize = sizeof(M4_StreamHandler);
1791        (*pStreamHandler)->m_bStreamIsOK = M4OSA_TRUE;
1792
1793        meta->findInt64(kKeyDuration,
1794            (int64_t*)&(Duration));
1795
1796        (*pStreamHandler)->m_duration = (int32_t)(Duration / 1000);
1797
1798        pC->mMaxDuration = ((*pStreamHandler)->m_duration);
1799        LOGV("VE str duration duration: %d ", (*pStreamHandler)->m_duration);
1800
1801        /* In AAC case: Put the first AU in pAudioStreamHandler->m_pUserData
1802         *since decoder has to know if stream contains SBR data(Implicit sig) */
1803        if(M4DA_StreamTypeAudioAac == (*pStreamHandler)->m_streamType) {
1804            M4READER_AudioSbrUserdata*  pAudioSbrUserdata;
1805
1806            pAudioSbrUserdata = (M4READER_AudioSbrUserdata*)M4OSA_malloc(
1807                sizeof(M4READER_AudioSbrUserdata),M4READER_3GP,
1808                (M4OSA_Char*)"M4READER_AudioSbrUserdata");
1809            if (M4OSA_NULL == pAudioSbrUserdata) {
1810                err = M4ERR_ALLOC;
1811                goto Error;
1812            }
1813            (*pStreamHandler)->m_pUserData = pAudioSbrUserdata;
1814            pAudioSbrUserdata->m_bIsSbrEnabled = M4OSA_FALSE;
1815
1816            pAudioSbrUserdata->m_pFirstAU = (M4_AccessUnit*)M4OSA_malloc(
1817                sizeof(M4_AccessUnit),M4READER_3GP, (M4OSA_Char*)"1st AAC AU");
1818            if (M4OSA_NULL == pAudioSbrUserdata->m_pFirstAU) {
1819                pAudioSbrUserdata->m_pAacDecoderUserConfig = M4OSA_NULL;
1820                err = M4ERR_ALLOC;
1821                goto Error;
1822            }
1823            pAudioSbrUserdata->m_pAacDecoderUserConfig = (M4_AacDecoderConfig*)\
1824                M4OSA_malloc(sizeof(M4_AacDecoderConfig),M4READER_3GP,
1825                (M4OSA_Char*)"m_pAacDecoderUserConfig");
1826            if (M4OSA_NULL == pAudioSbrUserdata->m_pAacDecoderUserConfig) {
1827                err = M4ERR_ALLOC;
1828                goto Error;
1829            }
1830        }
1831        if(M4DA_StreamTypeAudioAac == (*pStreamHandler)->m_streamType) {
1832            M4_AudioStreamHandler* pAudioStreamHandler =
1833                (M4_AudioStreamHandler*)(*pStreamHandler);
1834            M4READER_AudioSbrUserdata* pUserData = (M4READER_AudioSbrUserdata*)\
1835                (pAudioStreamHandler->m_basicProperties.m_pUserData);
1836
1837            err = VideoEditor3gpReader_fillAuStruct(pC, (*pStreamHandler),
1838                (M4_AccessUnit*)pUserData->m_pFirstAU);
1839            if (M4NO_ERROR != err) {
1840                goto Error;
1841            }
1842            err = VideoEditor3gpReader_getNextAu(pC, (*pStreamHandler),
1843                (M4_AccessUnit*)pUserData->m_pFirstAU);
1844            if (M4NO_ERROR != err) {
1845                goto Error;
1846            }
1847            err = VideoEditor3gpReader_reset(pC, (*pStreamHandler));
1848            if (M4NO_ERROR != err) {
1849                goto Error;
1850            }
1851        }
1852    }
1853    pC->mCurrTrack++; //Increment the current track to get next track
1854    LOGV("pC->mCurrTrack = %d",pC->mCurrTrack);
1855
1856    if (!haveAudio && !haveVideo) {
1857        *pMediaFamily=M4READER_kMediaFamilyUnknown;
1858        return M4ERR_READER_UNKNOWN_STREAM_TYPE;
1859    }
1860Error:
1861    LOGV("VideoEditor3gpReader_getNextStreamHandler end error = %d",err);
1862    return err;
1863}
1864
1865M4OSA_ERR VideoEditor3gpReader_getPrevRapTime(M4OSA_Context context,
1866    M4_StreamHandler *pStreamHandler, M4OSA_Int32* pTime)
1867{
1868    VideoEditor3gpReader_Context *pC = (VideoEditor3gpReader_Context*)context;
1869    M4OSA_ERR err = M4NO_ERROR;
1870    MediaBuffer *mMediaBuffer = M4OSA_NULL;
1871    MediaSource::ReadOptions options;
1872    M4OSA_Time time64;
1873    int64_t tempTime64 = 0;
1874    status_t error;
1875
1876    LOGV("VideoEditor3gpReader_getPrevRapTime begin");
1877
1878    M4OSA_DEBUG_IF1((pC == 0), M4ERR_PARAMETER,
1879        "VideoEditor3gpReader_getPrevRapTime: invalid context");
1880    M4OSA_DEBUG_IF1((pStreamHandler == 0), M4ERR_PARAMETER,
1881        "VideoEditor3gpReader_getPrevRapTime invalid pointer to StreamHandler");
1882    M4OSA_DEBUG_IF1((pTime == 0), M4ERR_PARAMETER,
1883        "VideoEditor3gpReader_getPrevRapTime: invalid time pointer");
1884    if (*pTime == (pStreamHandler->m_duration)) {
1885        *pTime -= 1;
1886    }
1887    M4OSA_INT64_FROM_INT32(time64, *pTime);
1888    time64 = time64 * 1000;
1889
1890    LOGV("VideoEditor3gpReader_getPrevRapTime seek time: %ld",time64);
1891    options.setSeekTo(time64, MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC);
1892    error = pC->mVideoSource->read(&mMediaBuffer, &options);
1893    if (error != OK) {
1894        //Can not get the previous Sync.
1895        //Must be end of stream.
1896        return M4WAR_NO_MORE_AU;
1897    }
1898
1899    mMediaBuffer->meta_data()->findInt64(kKeyTime, (int64_t*)&tempTime64);
1900    LOGV("VideoEditor3gpReader_getPrevRapTime read time %ld, %x", tempTime64,
1901        mMediaBuffer);
1902
1903    (*pTime) =  (tempTime64) / 1000;
1904
1905    if(mMediaBuffer != M4OSA_NULL) {
1906        LOGV(" mMediaBuffer size = %d length %d", mMediaBuffer->size(),
1907            mMediaBuffer->range_length());
1908        mMediaBuffer->release();
1909        mMediaBuffer = M4OSA_NULL;
1910    }
1911    options.clearSeekTo();
1912
1913    if(error != OK) {
1914        LOGV("VideoEditor3gpReader_getPrevRapTime end \
1915            M4WAR_READER_INFORMATION_NOT_PRESENT");
1916        return M4WAR_READER_INFORMATION_NOT_PRESENT;
1917    } else {
1918        LOGV("VideoEditor3gpReader_getPrevRapTime end: err %x", err);
1919        err = M4NO_ERROR;
1920        return err;
1921    }
1922}
1923
1924extern "C" {
1925M4OSA_ERR VideoEditor3gpReader_getInterface(M4READER_MediaType *pMediaType,
1926        M4READER_GlobalInterface **pRdrGlobalInterface,
1927        M4READER_DataInterface **pRdrDataInterface) {
1928
1929    M4OSA_ERR err = M4NO_ERROR;
1930
1931    VIDEOEDITOR_CHECK(M4OSA_NULL != pMediaType,      M4ERR_PARAMETER);
1932    VIDEOEDITOR_CHECK(M4OSA_NULL != pRdrGlobalInterface, M4ERR_PARAMETER);
1933    VIDEOEDITOR_CHECK(M4OSA_NULL != pRdrDataInterface, M4ERR_PARAMETER);
1934
1935    LOGV("VideoEditor3gpReader_getInterface begin");
1936    LOGV("VideoEditor3gpReader_getInterface %d 0x%x 0x%x", *pMediaType,
1937        *pRdrGlobalInterface,*pRdrDataInterface);
1938
1939    SAFE_MALLOC(*pRdrGlobalInterface, M4READER_GlobalInterface, 1,
1940        "VideoEditor3gpReader_getInterface");
1941    SAFE_MALLOC(*pRdrDataInterface, M4READER_DataInterface, 1,
1942        "VideoEditor3gpReader_getInterface");
1943
1944    *pMediaType = M4READER_kMediaType3GPP;
1945
1946    (*pRdrGlobalInterface)->m_pFctCreate       = VideoEditor3gpReader_create;
1947    (*pRdrGlobalInterface)->m_pFctDestroy      = VideoEditor3gpReader_destroy;
1948    (*pRdrGlobalInterface)->m_pFctOpen         = VideoEditor3gpReader_open;
1949    (*pRdrGlobalInterface)->m_pFctClose        = VideoEditor3gpReader_close;
1950    (*pRdrGlobalInterface)->m_pFctGetOption    = VideoEditor3gpReader_getOption;
1951    (*pRdrGlobalInterface)->m_pFctSetOption    = VideoEditor3gpReader_setOption;
1952    (*pRdrGlobalInterface)->m_pFctGetNextStream =
1953        VideoEditor3gpReader_getNextStreamHandler;
1954    (*pRdrGlobalInterface)->m_pFctFillAuStruct =
1955        VideoEditor3gpReader_fillAuStruct;
1956    (*pRdrGlobalInterface)->m_pFctStart        = M4OSA_NULL;
1957    (*pRdrGlobalInterface)->m_pFctStop         = M4OSA_NULL;
1958    (*pRdrGlobalInterface)->m_pFctJump         = VideoEditor3gpReader_jump;
1959    (*pRdrGlobalInterface)->m_pFctReset        = VideoEditor3gpReader_reset;
1960    (*pRdrGlobalInterface)->m_pFctGetPrevRapTime =
1961        VideoEditor3gpReader_getPrevRapTime;
1962    (*pRdrDataInterface)->m_pFctGetNextAu      = VideoEditor3gpReader_getNextAu;
1963    (*pRdrDataInterface)->m_readerContext      = M4OSA_NULL;
1964
1965cleanUp:
1966    if( M4NO_ERROR == err ) {
1967        LOGV("VideoEditor3gpReader_getInterface no error");
1968    } else {
1969        SAFE_FREE(*pRdrGlobalInterface);
1970        SAFE_FREE(*pRdrDataInterface);
1971
1972        LOGV("VideoEditor3gpReader_getInterface ERROR 0x%X", err);
1973    }
1974    LOGV("VideoEditor3gpReader_getInterface end");
1975    return err;
1976}
1977
1978}  /* extern "C" */
1979
1980}  /* namespace android */
1981
1982
1983