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