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 M4VSS3GPP_Clip.c 19 * @brief Implementation of functions related to input clip management. 20 * @note All functions in this file are static, i.e. non public 21 ****************************************************************************** 22 */ 23 24/****************/ 25/*** Includes ***/ 26/****************/ 27 28#include "NXPSW_CompilerSwitches.h" 29/** 30 * Our headers */ 31#include "M4VSS3GPP_API.h" 32#include "M4VSS3GPP_ErrorCodes.h" 33#include "M4VSS3GPP_InternalTypes.h" 34#include "M4VSS3GPP_InternalFunctions.h" 35#include "M4VSS3GPP_InternalConfig.h" 36 37/** 38 * OSAL headers */ 39#include "M4OSA_Memory.h" /* OSAL memory management */ 40#include "M4OSA_Debug.h" /* OSAL debug management */ 41 42 43/** 44 * Common headers (for aac) */ 45#include "M4_Common.h" 46 47#ifdef M4VSS_ENABLE_EXTERNAL_DECODERS 48#include "M4VD_EXTERNAL_Interface.h" 49 50#endif /* M4VSS_ENABLE_EXTERNAL_DECODERS */ 51 52/* Osal header fileno */ 53#include "M4OSA_CharStar.h" 54 55/** 56 ****************************************************************************** 57 * define Static function prototypes 58 ****************************************************************************** 59 */ 60 61static M4OSA_ERR M4VSS3GPP_intClipPrepareAudioDecoder( 62 M4VSS3GPP_ClipContext *pClipCtxt ); 63 64static M4OSA_ERR M4VSS3GPP_intCheckAndGetCodecAacProperties( 65 M4VSS3GPP_ClipContext *pClipCtxt); 66 67/** 68 ****************************************************************************** 69 * M4OSA_ERR M4VSS3GPP_intClipOpen() 70 * @brief Open a clip. Creates a clip context. 71 * @note 72 * @param hClipCtxt (OUT) Return the internal clip context 73 * @param pClipSettings (IN) Edit settings of this clip. The module will keep a 74 * reference to this pointer 75 * @param pFileReadPtrFct (IN) Pointer to OSAL file reader functions 76 * @param bSkipAudioTrack (IN) If true, do not open the audio 77 * @param bFastOpenMode (IN) If true, use the fast mode of the 3gpp reader 78 * (only the first AU is read) 79 * @return M4NO_ERROR: No error 80 * @return M4ERR_ALLOC: There is no more available memory 81 ****************************************************************************** 82 */ 83 84M4OSA_ERR M4VSS3GPP_intClipInit( M4VSS3GPP_ClipContext ** hClipCtxt, 85 M4OSA_FileReadPointer *pFileReadPtrFct ) 86{ 87 M4VSS3GPP_ClipContext *pClipCtxt; 88 M4OSA_ERR err; 89 90 M4OSA_DEBUG_IF2((M4OSA_NULL == hClipCtxt), M4ERR_PARAMETER, 91 "M4VSS3GPP_intClipInit: hClipCtxt is M4OSA_NULL"); 92 M4OSA_DEBUG_IF2((M4OSA_NULL == pFileReadPtrFct), M4ERR_PARAMETER, 93 "M4VSS3GPP_intClipInit: pFileReadPtrFct is M4OSA_NULL"); 94 95 /** 96 * Allocate the clip context */ 97 *hClipCtxt = 98 (M4VSS3GPP_ClipContext *)M4OSA_32bitAlignedMalloc(sizeof(M4VSS3GPP_ClipContext), 99 M4VSS3GPP, (M4OSA_Char *)"M4VSS3GPP_ClipContext"); 100 101 if( M4OSA_NULL == *hClipCtxt ) 102 { 103 M4OSA_TRACE1_0( 104 "M4VSS3GPP_intClipInit(): unable to allocate M4VSS3GPP_ClipContext,\ 105 returning M4ERR_ALLOC"); 106 return M4ERR_ALLOC; 107 } 108 M4OSA_TRACE3_1("M4VSS3GPP_intClipInit(): clipCtxt=0x%x", *hClipCtxt); 109 110 111 /** 112 * Use this shortcut to simplify the code */ 113 pClipCtxt = *hClipCtxt; 114 115 /* Inialization of context Variables */ 116 memset((void *)pClipCtxt, 0,sizeof(M4VSS3GPP_ClipContext)); 117 118 pClipCtxt->pSettings = M4OSA_NULL; 119 120 /** 121 * Init the clip context */ 122 pClipCtxt->iVoffset = 0; 123 pClipCtxt->iAoffset = 0; 124 pClipCtxt->Vstatus = M4VSS3GPP_kClipStatus_READ; 125 pClipCtxt->Astatus = M4VSS3GPP_kClipStatus_READ; 126 127 pClipCtxt->pReaderContext = M4OSA_NULL; 128 pClipCtxt->pVideoStream = M4OSA_NULL; 129 pClipCtxt->pAudioStream = M4OSA_NULL; 130 pClipCtxt->VideoAU.m_dataAddress = M4OSA_NULL; 131 pClipCtxt->AudioAU.m_dataAddress = M4OSA_NULL; 132 133 pClipCtxt->pViDecCtxt = M4OSA_NULL; 134 pClipCtxt->iVideoDecCts = 0; 135 pClipCtxt->iVideoRenderCts = 0; 136 pClipCtxt->lastDecodedPlane = M4OSA_NULL; 137 pClipCtxt->iActualVideoBeginCut = 0; 138 pClipCtxt->iActualAudioBeginCut = 0; 139 pClipCtxt->bVideoAuAvailable = M4OSA_FALSE; 140 pClipCtxt->bFirstAuWritten = M4OSA_FALSE; 141 142 pClipCtxt->bMpeg4GovState = M4OSA_FALSE; 143 144 pClipCtxt->bAudioFrameAvailable = M4OSA_FALSE; 145 pClipCtxt->pAudioFramePtr = M4OSA_NULL; 146 pClipCtxt->iAudioFrameCts = 0; 147 pClipCtxt->pAudioDecCtxt = 0; 148 pClipCtxt->AudioDecBufferOut.m_bufferSize = 0; 149 pClipCtxt->AudioDecBufferOut.m_dataAddress = M4OSA_NULL; 150 151 pClipCtxt->pFileReadPtrFct = pFileReadPtrFct; 152 pClipCtxt->pPlaneYuv = M4OSA_NULL; 153 pClipCtxt->pPlaneYuvWithEffect = M4OSA_NULL; 154 pClipCtxt->m_pPreResizeFrame = M4OSA_NULL; 155 pClipCtxt->bGetYuvDataFromDecoder = M4OSA_TRUE; 156 157 /* 158 * Reset pointers for media and codecs interfaces */ 159 err = M4VSS3GPP_clearInterfaceTables(&pClipCtxt->ShellAPI); 160 M4ERR_CHECK_RETURN(err); 161 162 /* 163 * Call the media and codecs subscription module */ 164 err = M4VSS3GPP_subscribeMediaAndCodec(&pClipCtxt->ShellAPI); 165 M4ERR_CHECK_RETURN(err); 166 167 return M4NO_ERROR; 168} 169 170// This method maps the frequency value to a string. 171static const char* freqToString(int freq) { 172 switch (freq) { 173 case 8000: 174 return "_8000"; 175 case 11025: 176 return "_11025"; 177 case 12000: 178 return "_12000"; 179 case 16000: 180 return "_16000"; 181 case 22050: 182 return "_22050"; 183 case 24000: 184 return "_24000"; 185 case 32000: 186 return "_32000"; 187 case 44100: 188 return "_44100"; 189 case 48000: 190 return "_48000"; 191 default: 192 M4OSA_TRACE1_1("Unsupported sampling rate: %d Hz", freq); 193 return NULL; 194 } 195} 196 197// This method maps the number of channel value to 198// a string that will be part of a file name extension 199static const char* channelToStringAndFileExt(int channels) { 200 switch (channels) { 201 case 1: 202 return "_1.pcm"; 203 case 2: 204 return "_2.pcm"; 205 default: 206 M4OSA_TRACE1_1("Unsupported %d channels", channels); 207 return NULL; 208 } 209} 210 211/* Note: if the clip is opened in fast mode, it can only be used for analysis and nothing else. */ 212M4OSA_ERR M4VSS3GPP_intClipOpen( M4VSS3GPP_ClipContext *pClipCtxt, 213 M4VSS3GPP_ClipSettings *pClipSettings, M4OSA_Bool bSkipAudioTrack, 214 M4OSA_Bool bFastOpenMode, M4OSA_Bool bAvoidOpeningVideoDec ) 215{ 216 M4OSA_ERR err; 217 M4READER_MediaFamily mediaFamily; 218 M4_StreamHandler *pStreamHandler; 219 M4_StreamHandler dummyStreamHandler; 220 M4OSA_Int32 iDuration; 221 M4OSA_Void *decoderUserData; 222#ifdef M4VSS_ENABLE_EXTERNAL_DECODERS 223 224 M4DECODER_MPEG4_DecoderConfigInfo dummy; 225 M4DECODER_VideoSize videoSizeFromDSI; 226#endif /* M4VSS_ENABLE_EXTERNAL_DECODERS */ 227 228 M4DECODER_OutputFilter FilterOption; 229 230 /** 231 * Check input parameters */ 232 M4OSA_DEBUG_IF2((M4OSA_NULL == pClipCtxt), M4ERR_PARAMETER, 233 "M4VSS3GPP_intClipOpen: pClipCtxt is M4OSA_NULL"); 234 M4OSA_DEBUG_IF2((M4OSA_NULL == pClipSettings), M4ERR_PARAMETER, 235 "M4VSS3GPP_intClipOpen: pClipSettings is M4OSA_NULL"); 236 237 M4OSA_TRACE3_2( 238 "M4VSS3GPP_intClipOpen: called with pClipCtxt: 0x%x, bAvoidOpeningVideoDec=0x%x", 239 pClipCtxt, bAvoidOpeningVideoDec); 240 /** 241 * Keep a pointer to the clip settings. Remember that we don't possess it! */ 242 pClipCtxt->pSettings = pClipSettings; 243 if(M4VIDEOEDITING_kFileType_ARGB8888 == pClipCtxt->pSettings->FileType) { 244 M4OSA_TRACE3_0("M4VSS3GPP_intClipOpen: Image stream; set current vid dec"); 245 err = M4VSS3GPP_setCurrentVideoDecoder( 246 &pClipCtxt->ShellAPI, M4DA_StreamTypeVideoARGB8888); 247 M4ERR_CHECK_RETURN(err); 248 249 decoderUserData = M4OSA_NULL; 250 251 err = pClipCtxt->ShellAPI.m_pVideoDecoder->m_pFctCreate( 252 &pClipCtxt->pViDecCtxt, 253 &dummyStreamHandler, 254 pClipCtxt->ShellAPI.m_pReader, 255 pClipCtxt->ShellAPI.m_pReaderDataIt, 256 &pClipCtxt->VideoAU, 257 decoderUserData); 258 259 if (M4NO_ERROR != err) { 260 M4OSA_TRACE1_1("M4VSS3GPP_intClipOpen: \ 261 m_pVideoDecoder->m_pFctCreate returns 0x%x", err); 262 return err; 263 } 264 M4OSA_TRACE3_1("M4VSS3GPP_intClipOpen: \ 265 Vid dec started; pViDecCtxt=0x%x", pClipCtxt->pViDecCtxt); 266 267 return M4NO_ERROR; 268 } 269 270 /** 271 * Get the correct reader interface */ 272 err = M4VSS3GPP_setCurrentReader(&pClipCtxt->ShellAPI, 273 pClipCtxt->pSettings->FileType); 274 M4ERR_CHECK_RETURN(err); 275 276 /** 277 * Init the 3GPP or MP3 reader */ 278 err = 279 pClipCtxt->ShellAPI.m_pReader->m_pFctCreate(&pClipCtxt->pReaderContext); 280 281 if( M4NO_ERROR != err ) 282 { 283 M4OSA_TRACE1_1( 284 "M4VSS3GPP_intClipOpen(): m_pReader->m_pFctCreate returns 0x%x", 285 err); 286 return err; 287 } 288 289 /** 290 * Link the reader interface to the reader context (used by the decoder to know the reader) */ 291 pClipCtxt->ShellAPI.m_pReaderDataIt->m_readerContext = 292 pClipCtxt->pReaderContext; 293 294 /** 295 * Set the OSAL read function set */ 296 err = pClipCtxt->ShellAPI.m_pReader->m_pFctSetOption( 297 pClipCtxt->pReaderContext, 298 M4READER_kOptionID_SetOsaFileReaderFctsPtr, 299 (M4OSA_DataOption)(pClipCtxt->pFileReadPtrFct)); 300 301 if( M4NO_ERROR != err ) 302 { 303 M4OSA_TRACE1_1( 304 "M4VSS3GPP_intClipOpen(): m_pReader->m_pFctSetOption returns 0x%x", 305 err); 306 return err; 307 } 308 309 /** 310 * Set the fast open mode if asked (3GPP only) */ 311 if( M4VIDEOEDITING_kFileType_3GPP == pClipCtxt->pSettings->FileType ) 312 { 313 if( M4OSA_TRUE == bFastOpenMode ) 314 { 315 err = pClipCtxt->ShellAPI.m_pReader->m_pFctSetOption( 316 pClipCtxt->pReaderContext, 317 M4READER_3GP_kOptionID_FastOpenMode, M4OSA_NULL); 318 319 if( M4NO_ERROR != err ) 320 { 321 M4OSA_TRACE1_1( 322 "M4VSS3GPP_intClipOpen():\ 323 m_pReader->m_pFctSetOption(FastOpenMode) returns 0x%x", 324 err); 325 return err; 326 } 327 } 328 329 /** 330 * Set the skip audio option if asked */ 331 if( M4OSA_TRUE == bSkipAudioTrack ) 332 { 333 err = pClipCtxt->ShellAPI.m_pReader->m_pFctSetOption( 334 pClipCtxt->pReaderContext, 335 M4READER_3GP_kOptionID_VideoOnly, M4OSA_NULL); 336 337 if( M4NO_ERROR != err ) 338 { 339 M4OSA_TRACE1_1( 340 "M4VSS3GPP_intClipOpen(): m_pReader->m_pFctSetOption(VideoOnly) returns 0x%x", 341 err); 342 return err; 343 } 344 } 345 } 346 if (pClipCtxt->pSettings->FileType == M4VIDEOEDITING_kFileType_PCM) { 347 // Compose the temp filename with sample rate and channel information. 348 const char* freqStr = freqToString( 349 pClipCtxt->pSettings->ClipProperties.uiSamplingFrequency); 350 351 if (freqStr == NULL) { 352 return M4VSS3GPP_WAR_INCOMPATIBLE_AUDIO_SAMPLING_FREQUENCY; 353 } 354 355 const char* chanStr = channelToStringAndFileExt( 356 pClipCtxt->pSettings->ClipProperties.uiNbChannels); 357 358 if (chanStr == NULL) { 359 return M4VSS3GPP_WAR_INCOMPATIBLE_AUDIO_NB_OF_CHANNELS; 360 } 361 362 // Allocate one byte more to hold the null terminator 363 M4OSA_UInt32 length = 364 strlen(pClipSettings->pFile) + strlen(freqStr) + strlen(chanStr) + 1; 365 366 char* pTempFile = (char *) malloc(length); 367 if (pTempFile == NULL) { 368 M4OSA_TRACE1_1("M4VSS3GPP_intClipOpen(): malloc %d bytes fail",length); 369 return M4ERR_ALLOC; 370 } 371 memset(pTempFile, 0, length); 372 memcpy(pTempFile, pClipSettings->pFile, strlen(pClipSettings->pFile)); 373 strncat(pTempFile, freqStr, strlen(freqStr)); 374 strncat(pTempFile, chanStr, strlen(chanStr)); 375 376 err = pClipCtxt->ShellAPI.m_pReader->m_pFctOpen( pClipCtxt->pReaderContext, pTempFile); 377 if (pTempFile != NULL) { 378 free(pTempFile); 379 pTempFile = NULL; 380 } 381 if ( M4NO_ERROR != err ) { 382 M4OSA_TRACE1_1("M4VSS3GPP_intClipOpen(): open pcm file returns error : 0x%x", err); 383 return err; 384 } 385 } 386 else 387 { 388 /** 389 * Open the 3GPP/MP3 clip file */ 390 err = pClipCtxt->ShellAPI.m_pReader->m_pFctOpen( pClipCtxt->pReaderContext, 391 pClipSettings->pFile); 392 } 393 if( M4NO_ERROR != err ) 394 { 395 M4OSA_UInt32 uiDummy, uiCoreId; 396 M4OSA_TRACE1_1( 397 "M4VSS3GPP_intClipOpen(): m_pReader->m_pFctOpen returns 0x%x", err); 398 399 /** 400 * If the error is from the core reader, we change it to a public VSS3GPP error */ 401 M4OSA_ERR_SPLIT(err, uiDummy, uiCoreId, uiDummy); 402 403 if( M4MP4_READER == uiCoreId ) 404 { 405 M4OSA_TRACE1_0( 406 "M4VSS3GPP_intClipOpen(): returning M4VSS3GPP_ERR_INVALID_3GPP_FILE"); 407 return M4VSS3GPP_ERR_INVALID_3GPP_FILE; 408 } 409 return err; 410 } 411 412 /** 413 * Get the audio and video streams */ 414 while( err == M4NO_ERROR ) 415 { 416 err = pClipCtxt->ShellAPI.m_pReader->m_pFctGetNextStream( 417 pClipCtxt->pReaderContext, &mediaFamily, &pStreamHandler); 418 419 /*in case we found a BIFS stream or something else...*/ 420 if( ( err == ((M4OSA_UInt32)M4ERR_READER_UNKNOWN_STREAM_TYPE)) 421 || (err == ((M4OSA_UInt32)M4WAR_TOO_MUCH_STREAMS)) ) 422 { 423 err = M4NO_ERROR; 424 continue; 425 } 426 427 if( M4NO_ERROR == err ) /**< One stream found */ 428 { 429 /** 430 * Found a video stream */ 431 if( ( mediaFamily == M4READER_kMediaFamilyVideo) 432 && (M4OSA_NULL == pClipCtxt->pVideoStream) ) 433 { 434 if( ( M4DA_StreamTypeVideoH263 == pStreamHandler->m_streamType) 435 || (M4DA_StreamTypeVideoMpeg4 436 == pStreamHandler->m_streamType) 437 || (M4DA_StreamTypeVideoMpeg4Avc 438 == pStreamHandler->m_streamType) ) 439 { 440 M4OSA_TRACE3_1( 441 "M4VSS3GPP_intClipOpen():\ 442 Found a H263 or MPEG-4 or H264 video stream in input 3gpp clip; %d", 443 pStreamHandler->m_streamType); 444 445 /** 446 * Keep pointer to the video stream */ 447 pClipCtxt->pVideoStream = 448 (M4_VideoStreamHandler *)pStreamHandler; 449 pStreamHandler->m_bStreamIsOK = M4OSA_TRUE; 450 451 /** 452 * Reset the stream reader */ 453 err = pClipCtxt->ShellAPI.m_pReader->m_pFctReset( 454 pClipCtxt->pReaderContext, 455 (M4_StreamHandler *)pClipCtxt->pVideoStream); 456 457 if( M4NO_ERROR != err ) 458 { 459 M4OSA_TRACE1_1( 460 "M4VSS3GPP_intClipOpen(): m_pReader->m_pFctReset(video) returns 0x%x", 461 err); 462 return err; 463 } 464 465 /** 466 * Initializes an access Unit */ 467 err = pClipCtxt->ShellAPI.m_pReader->m_pFctFillAuStruct( 468 pClipCtxt->pReaderContext, 469 (M4_StreamHandler *)pClipCtxt->pVideoStream, 470 &pClipCtxt->VideoAU); 471 472 if( M4NO_ERROR != err ) 473 { 474 M4OSA_TRACE1_1( 475 "M4VSS3GPP_intClipOpen():\ 476 m_pReader->m_pFctFillAuStruct(video) returns 0x%x", 477 err); 478 return err; 479 } 480 } 481 else /**< Not H263 or MPEG-4 (H264, etc.) */ 482 { 483 M4OSA_TRACE1_1( 484 "M4VSS_editClipOpen():\ 485 Found an unsupported video stream (0x%x) in input 3gpp clip", 486 pStreamHandler->m_streamType); 487 488 pStreamHandler->m_bStreamIsOK = M4OSA_FALSE; 489 } 490 } 491 /** 492 * Found an audio stream */ 493 else if( ( mediaFamily == M4READER_kMediaFamilyAudio) 494 && (M4OSA_NULL == pClipCtxt->pAudioStream) ) 495 { 496 if( ( M4DA_StreamTypeAudioAmrNarrowBand 497 == pStreamHandler->m_streamType) 498 || (M4DA_StreamTypeAudioAac == pStreamHandler->m_streamType) 499 || (M4DA_StreamTypeAudioMp3 500 == pStreamHandler->m_streamType) 501 || (M4DA_StreamTypeAudioEvrc 502 == pStreamHandler->m_streamType) 503 || (M4DA_StreamTypeAudioPcm 504 == pStreamHandler->m_streamType) ) 505 { 506 M4OSA_TRACE3_1( 507 "M4VSS3GPP_intClipOpen(): \ 508 Found an AMR-NB or AAC or MP3 audio stream in input clip; %d", 509 pStreamHandler->m_streamType); 510 511 /** 512 * Keep pointer to the audio stream */ 513 pClipCtxt->pAudioStream = 514 (M4_AudioStreamHandler *)pStreamHandler; 515 pStreamHandler->m_bStreamIsOK = M4OSA_TRUE; 516 517 /** 518 * Reset the stream reader */ 519 err = pClipCtxt->ShellAPI.m_pReader->m_pFctReset( 520 pClipCtxt->pReaderContext, 521 (M4_StreamHandler *)pClipCtxt->pAudioStream); 522 523 if( M4NO_ERROR != err ) 524 { 525 M4OSA_TRACE1_1( 526 "M4VSS3GPP_intClipOpen(): m_pReader->m_pFctReset(audio) returns 0x%x", 527 err); 528 return err; 529 } 530 531 /** 532 * Initializes an access Unit */ 533 err = pClipCtxt->ShellAPI.m_pReader->m_pFctFillAuStruct( 534 pClipCtxt->pReaderContext, 535 (M4_StreamHandler *)pClipCtxt->pAudioStream, 536 &pClipCtxt->AudioAU); 537 538 if( M4NO_ERROR != err ) 539 { 540 M4OSA_TRACE1_1( 541 "M4VSS3GPP_intClipOpen():\ 542 m_pReader->m_pFctFillAuStruct(audio) returns 0x%x", 543 err); 544 return err; 545 } 546 } 547 else /**< Not AMR-NB or AAC (AMR-WB...) */ 548 { 549 M4OSA_TRACE1_1( 550 "M4VSS3GPP_intClipOpen():\ 551 Found an unsupported audio stream (0x%x) in input 3gpp/mp3 clip", 552 pStreamHandler->m_streamType); 553 554 pStreamHandler->m_bStreamIsOK = M4OSA_FALSE; 555 } 556 } 557 } 558 else if( M4OSA_ERR_IS_ERROR(err) ) 559 { 560 M4OSA_TRACE1_1( 561 "M4VSS3GPP_intClipOpen(): m_pReader->m_pFctGetNextStream() returns 0x%x!", 562 err); 563 return err; 564 } 565 } 566 567 /** 568 * Init Video decoder */ 569 if( M4OSA_NULL != pClipCtxt->pVideoStream ) 570 { 571#ifdef M4VSS_ENABLE_EXTERNAL_DECODERS 572 /* If external decoders are possible, it's best to avoid opening the decoder if the clip is only 573 going to be used for analysis, as we're not going to use it for the analysis in the case of a 574 possible external decoder anyway, and either there could be no decoder at this point or the HW 575 decoder could be present, which we want to avoid opening for that. See comments in 576 intBuildAnalysis for more details. */ 577 578 /* CHANGEME Temporarily only do this for MPEG4, since for now only MPEG4 external decoders are 579 supported, and the following wouldn't work for H263 so a release where external decoders are 580 possible, but not used, wouldn't work with H263 stuff. */ 581 582 if( bAvoidOpeningVideoDec && M4DA_StreamTypeVideoMpeg4 583 == pClipCtxt->pVideoStream->m_basicProperties.m_streamType ) 584 { 585 /* Oops! The mere act of opening the decoder also results in the image size being 586 filled in the video stream! Compensate for this by using ParseVideoDSI to fill 587 this info. */ 588 M4OSA_TRACE3_0( 589 "M4VSS3GPP_intClipOpen: Mpeg4 stream; vid dec not started"); 590 err = M4DECODER_EXTERNAL_ParseVideoDSI(pClipCtxt->pVideoStream-> 591 m_basicProperties.m_pDecoderSpecificInfo, 592 pClipCtxt->pVideoStream-> 593 m_basicProperties.m_decoderSpecificInfoSize, 594 &dummy, &videoSizeFromDSI); 595 596 pClipCtxt->pVideoStream->m_videoWidth = videoSizeFromDSI.m_uiWidth; 597 pClipCtxt->pVideoStream->m_videoHeight = 598 videoSizeFromDSI.m_uiHeight; 599 } 600 else 601 { 602 603#endif 604 605 M4OSA_TRACE3_0( 606 "M4VSS3GPP_intClipOpen: Mp4/H263/H264 stream; set current vid dec"); 607 err = M4VSS3GPP_setCurrentVideoDecoder(&pClipCtxt->ShellAPI, 608 pClipCtxt->pVideoStream->m_basicProperties.m_streamType); 609 M4ERR_CHECK_RETURN(err); 610 611#ifdef M4VSS_ENABLE_EXTERNAL_DECODERS 612 613 decoderUserData = 614 pClipCtxt->ShellAPI.m_pCurrentVideoDecoderUserData; 615 616#else 617 618 decoderUserData = M4OSA_NULL; 619 620#endif 621 622 err = pClipCtxt->ShellAPI.m_pVideoDecoder->m_pFctCreate( 623 &pClipCtxt->pViDecCtxt, 624 &pClipCtxt->pVideoStream->m_basicProperties, 625 pClipCtxt->ShellAPI.m_pReader, 626 pClipCtxt->ShellAPI.m_pReaderDataIt, 627 &pClipCtxt->VideoAU, decoderUserData); 628 629 if( ( ((M4OSA_UInt32)M4ERR_DECODER_H263_PROFILE_NOT_SUPPORTED) == err) 630 || (((M4OSA_UInt32)M4ERR_DECODER_H263_NOT_BASELINE) == err) ) 631 { 632 /** 633 * Our decoder is not compatible with H263 profile other than 0. 634 * So it returns this internal error code. 635 * We translate it to our own error code */ 636 return M4VSS3GPP_ERR_H263_PROFILE_NOT_SUPPORTED; 637 } 638 else if( M4NO_ERROR != err ) 639 { 640 M4OSA_TRACE1_1( 641 "M4VSS3GPP_intClipOpen: m_pVideoDecoder->m_pFctCreate returns 0x%x", 642 err); 643 return err; 644 } 645 M4OSA_TRACE3_1( 646 "M4VSS3GPP_intClipOpen: Vid dec started; pViDecCtxt=0x%x", 647 pClipCtxt->pViDecCtxt); 648 649 if( M4DA_StreamTypeVideoMpeg4Avc 650 == pClipCtxt->pVideoStream->m_basicProperties.m_streamType ) 651 { 652 FilterOption.m_pFilterFunction = 653 (M4OSA_Void *) &M4VIFI_ResizeBilinearYUV420toYUV420; 654 FilterOption.m_pFilterUserData = M4OSA_NULL; 655 err = pClipCtxt->ShellAPI.m_pVideoDecoder->m_pFctSetOption( 656 pClipCtxt->pViDecCtxt, M4DECODER_kOptionID_OutputFilter, 657 (M4OSA_DataOption) &FilterOption); 658 659 if( M4NO_ERROR != err ) 660 { 661 M4OSA_TRACE1_1( 662 "M4VSS3GPP_intClipOpen: m_pVideoDecoder->m_pFctSetOption returns 0x%x", 663 err); 664 return err; 665 } 666 else 667 { 668 M4OSA_TRACE3_0( 669 "M4VSS3GPP_intClipOpen: m_pVideoDecoder->m_pFctSetOption\ 670 M4DECODER_kOptionID_OutputFilter OK"); 671 } 672 } 673#ifdef M4VSS_ENABLE_EXTERNAL_DECODERS 674 675 } 676 677#endif 678 679 } 680 681 /** 682 * Init Audio decoder */ 683 if( M4OSA_NULL != pClipCtxt->pAudioStream ) 684 { 685 err = M4VSS3GPP_intClipPrepareAudioDecoder(pClipCtxt); 686 M4ERR_CHECK_RETURN(err); 687 M4OSA_TRACE3_1("M4VSS3GPP_intClipOpen: Audio dec started; context=0x%x", 688 pClipCtxt->pAudioDecCtxt); 689 } 690 else 691 { 692 pClipCtxt->AudioAU.m_streamID = 0; 693 pClipCtxt->AudioAU.m_dataAddress = M4OSA_NULL; 694 pClipCtxt->AudioAU.m_size = 0; 695 pClipCtxt->AudioAU.m_CTS = 0; 696 pClipCtxt->AudioAU.m_DTS = 0; 697 pClipCtxt->AudioAU.m_attribute = 0; 698 pClipCtxt->AudioAU.m_maxsize = 0; 699 pClipCtxt->AudioAU.m_structSize = sizeof(pClipCtxt->AudioAU); 700 } 701 702 /** 703 * Get the duration of the longest stream */ 704 if( M4OSA_TRUE == pClipCtxt->pSettings->ClipProperties.bAnalysed ) 705 { 706 /* If already calculated set it to previous value */ 707 /* Because fast open and full open can return a different value, 708 it can mismatch user settings */ 709 /* Video track is more important than audio track (if video track is shorter than 710 audio track, it can led to cut larger than expected) */ 711 iDuration = pClipCtxt->pSettings->ClipProperties.uiClipVideoDuration; 712 713 if( iDuration == 0 ) 714 { 715 iDuration = pClipCtxt->pSettings->ClipProperties.uiClipDuration; 716 } 717 } 718 else 719 { 720 /* Else compute it from streams */ 721 iDuration = 0; 722 723 if( M4OSA_NULL != pClipCtxt->pVideoStream ) 724 { 725 iDuration = (M4OSA_Int32)( 726 pClipCtxt->pVideoStream->m_basicProperties.m_duration); 727 } 728 729 if( ( M4OSA_NULL != pClipCtxt->pAudioStream) && ((M4OSA_Int32)( 730 pClipCtxt->pAudioStream->m_basicProperties.m_duration) 731 > iDuration) && iDuration == 0 ) 732 { 733 iDuration = (M4OSA_Int32)( 734 pClipCtxt->pAudioStream->m_basicProperties.m_duration); 735 } 736 } 737 738 /** 739 * If end time is not used, we set it to the video track duration */ 740 if( 0 == pClipCtxt->pSettings->uiEndCutTime ) 741 { 742 pClipCtxt->pSettings->uiEndCutTime = (M4OSA_UInt32)iDuration; 743 } 744 745 pClipCtxt->iEndTime = (M4OSA_Int32)pClipCtxt->pSettings->uiEndCutTime; 746 747 /** 748 * Return with no error */ 749 M4OSA_TRACE3_0("M4VSS3GPP_intClipOpen(): returning M4NO_ERROR"); 750 return M4NO_ERROR; 751} 752 753/** 754 ****************************************************************************** 755 * M4OSA_Void M4VSS3GPP_intClipDeleteAudioTrack() 756 * @brief Delete the audio track. Clip will be like if it had no audio track 757 * @note 758 * @param pClipCtxt (IN) Internal clip context 759 ****************************************************************************** 760 */ 761M4OSA_Void M4VSS3GPP_intClipDeleteAudioTrack( M4VSS3GPP_ClipContext *pClipCtxt ) 762{ 763 /** 764 * But we don't have to free the audio stream. It will be freed by the reader when closing it*/ 765 pClipCtxt->pAudioStream = M4OSA_NULL; 766 767 /** 768 * We will return a constant silence AMR AU. 769 * We set it here once, instead of at each read audio step. */ 770 pClipCtxt->pAudioFramePtr = (M4OSA_MemAddr8)pClipCtxt->pSilenceFrameData; 771 pClipCtxt->uiAudioFrameSize = pClipCtxt->uiSilenceFrameSize; 772 773 /** 774 * Free the decoded audio buffer (it needs to be re-allocated to store silence 775 frame eventually)*/ 776 if( M4OSA_NULL != pClipCtxt->AudioDecBufferOut.m_dataAddress ) 777 { 778 free(pClipCtxt->AudioDecBufferOut.m_dataAddress); 779 pClipCtxt->AudioDecBufferOut.m_dataAddress = M4OSA_NULL; 780 } 781 782 return; 783} 784 785/** 786 ****************************************************************************** 787 * M4OSA_ERR M4VSS3GPP_intClipDecodeVideoUpToCurrentTime() 788 * @brief Jump to the previous RAP and decode up to the current video time 789 * @param pClipCtxt (IN) Internal clip context 790 * @param iCts (IN) Target CTS 791 ****************************************************************************** 792 */ 793M4OSA_ERR M4VSS3GPP_intClipDecodeVideoUpToCts( M4VSS3GPP_ClipContext *pClipCtxt, 794 M4OSA_Int32 iCts ) 795{ 796 M4OSA_Int32 iRapCts, iClipCts; 797 M4_MediaTime dDecodeTime; 798 M4OSA_Bool bClipJump = M4OSA_FALSE; 799 M4OSA_ERR err; 800 801 /** 802 * Compute the time in the clip base */ 803 iClipCts = iCts - pClipCtxt->iVoffset; 804 805 /** 806 * If we were reading the clip, we must jump to the previous RAP 807 * to decode from that point. */ 808 if( M4VSS3GPP_kClipStatus_READ == pClipCtxt->Vstatus ) 809 { 810 /** 811 * The decoder must be told to jump */ 812 bClipJump = M4OSA_TRUE; 813 pClipCtxt->iVideoDecCts = iClipCts; 814 815 /** 816 * Remember the clip reading state */ 817 pClipCtxt->Vstatus = M4VSS3GPP_kClipStatus_DECODE_UP_TO; 818 } 819 820 /** 821 * If we are in decodeUpTo() process, check if we need to do 822 one more step or if decoding is finished */ 823 if( M4VSS3GPP_kClipStatus_DECODE_UP_TO == pClipCtxt->Vstatus ) 824 { 825 /* Do a step of 500 ms decoding */ 826 pClipCtxt->iVideoDecCts += 500; 827 828 if( pClipCtxt->iVideoDecCts > iClipCts ) 829 { 830 /* Target time reached, we switch back to DECODE mode */ 831 pClipCtxt->iVideoDecCts = iClipCts; 832 pClipCtxt->Vstatus = M4VSS3GPP_kClipStatus_DECODE; 833 } 834 835 M4OSA_TRACE2_1("c ,,,, decode up to : %ld", pClipCtxt->iVideoDecCts); 836 } 837 else 838 { 839 /* Just decode at current clip cts */ 840 pClipCtxt->iVideoDecCts = iClipCts; 841 842 M4OSA_TRACE2_1("d ,,,, decode up to : %ld", pClipCtxt->iVideoDecCts); 843 } 844 845 /** 846 * Decode up to the target */ 847 M4OSA_TRACE3_2( 848 "M4VSS3GPP_intClipDecodeVideoUpToCts: Decoding upTo CTS %.3f, pClipCtxt=0x%x", 849 dDecodeTime, pClipCtxt); 850 851 dDecodeTime = (M4OSA_Double)pClipCtxt->iVideoDecCts; 852 pClipCtxt->isRenderDup = M4OSA_FALSE; 853 err = 854 pClipCtxt->ShellAPI.m_pVideoDecoder->m_pFctDecode(pClipCtxt->pViDecCtxt, 855 &dDecodeTime, bClipJump, 0); 856 857 if( ( M4NO_ERROR != err) && (M4WAR_NO_MORE_AU != err) 858 && (err != M4WAR_VIDEORENDERER_NO_NEW_FRAME) ) 859 { 860 M4OSA_TRACE1_1( 861 "M4VSS3GPP_intClipDecodeVideoUpToCts: m_pFctDecode returns 0x%x!", 862 err); 863 return err; 864 } 865 866 if( err == M4WAR_VIDEORENDERER_NO_NEW_FRAME ) 867 { 868 pClipCtxt->isRenderDup = M4OSA_TRUE; 869 } 870 871 /** 872 * Return */ 873 M4OSA_TRACE3_0("M4VSS3GPP_intClipDecodeVideoUpToCts: returning M4NO_ERROR"); 874 return M4NO_ERROR; 875} 876 877/** 878 ****************************************************************************** 879 * M4OSA_ERR M4VSS3GPP_intClipReadNextAudioFrame() 880 * @brief Read one AU frame in the clip 881 * @note 882 * @param pClipCtxt (IN) Internal clip context 883 * @return M4NO_ERROR: No error 884 ****************************************************************************** 885 */ 886M4OSA_ERR M4VSS3GPP_intClipReadNextAudioFrame( 887 M4VSS3GPP_ClipContext *pClipCtxt ) 888{ 889 M4OSA_ERR err; 890 891 /* ------------------------------ */ 892 /* ---------- NO AUDIO ---------- */ 893 /* ------------------------------ */ 894 895 if( M4OSA_NULL == pClipCtxt->pAudioStream ) 896 { 897 /* If there is no audio track, we return silence AUs */ 898 pClipCtxt->pAudioFramePtr = 899 (M4OSA_MemAddr8)pClipCtxt->pSilenceFrameData; 900 pClipCtxt->uiAudioFrameSize = pClipCtxt->uiSilenceFrameSize; 901 pClipCtxt->iAudioFrameCts += pClipCtxt->iSilenceFrameDuration; 902 903 M4OSA_TRACE2_0("b #### blank track"); 904 } 905 906 /* ---------------------------------- */ 907 /* ---------- AMR-NB, EVRC ---------- */ 908 /* ---------------------------------- */ 909 910 else if( ( M4VIDEOEDITING_kAMR_NB 911 == pClipCtxt->pSettings->ClipProperties.AudioStreamType) 912 || (M4VIDEOEDITING_kEVRC 913 == pClipCtxt->pSettings->ClipProperties.AudioStreamType) ) 914 { 915 if( M4OSA_FALSE == pClipCtxt->bAudioFrameAvailable ) 916 { 917 /** 918 * No AU available, so we must must read one from the original track reader */ 919 err = pClipCtxt->ShellAPI.m_pReaderDataIt->m_pFctGetNextAu( 920 pClipCtxt->pReaderContext, 921 (M4_StreamHandler *)pClipCtxt->pAudioStream, 922 &pClipCtxt->AudioAU); 923 924 if( M4NO_ERROR == err ) 925 { 926 /** 927 * Set the current AMR frame position at the beginning of the read AU */ 928 pClipCtxt->pAudioFramePtr = pClipCtxt->AudioAU.m_dataAddress; 929 930 /** 931 * Set the AMR frame CTS */ 932 pClipCtxt->iAudioFrameCts = 933 (M4OSA_Int32)(pClipCtxt->AudioAU.m_CTS 934 * pClipCtxt->scale_audio + 0.5); 935 } 936 else if( ( M4WAR_NO_MORE_AU == err) && (M4VIDEOEDITING_kAMR_NB 937 == pClipCtxt->pSettings->ClipProperties.AudioStreamType) ) 938 { 939 /** 940 * If there is less audio than the stream duration indicated, 941 * we return silence at the end of the stream. */ 942 pClipCtxt->pAudioFramePtr = 943 (M4OSA_MemAddr8)pClipCtxt->pSilenceFrameData; 944 pClipCtxt->uiAudioFrameSize = pClipCtxt->uiSilenceFrameSize; 945 pClipCtxt->iAudioFrameCts += pClipCtxt->iSilenceFrameDuration; 946 947 M4OSA_TRACE2_0("a #### silence AU"); 948 949 /** 950 * Return with M4WAR_NO_MORE_AU */ 951 M4OSA_TRACE3_0( 952 "M4VSS3GPP_intClipReadNextAudioFrame()-AMR: \ 953 returning M4WAR_NO_MORE_AU (silence)"); 954 return M4WAR_NO_MORE_AU; 955 } 956 else /**< fatal error (or no silence in EVRC) */ 957 { 958 M4OSA_TRACE3_1( 959 "M4VSS3GPP_intClipReadNextAudioFrame()-AMR: m_pFctGetNextAu() returns 0x%x", 960 err); 961 return err; 962 } 963 } 964 else /* bAudioFrameAvailable */ 965 { 966 /** 967 * Go to the next AMR frame in the AU */ 968 pClipCtxt->pAudioFramePtr += pClipCtxt->uiAudioFrameSize; 969 970 /** 971 * Increment CTS: one AMR frame is 20 ms long */ 972 pClipCtxt->iAudioFrameCts += pClipCtxt->iSilenceFrameDuration; 973 } 974 975 /** 976 * Get the size of the pointed AMR frame */ 977 switch( pClipCtxt->pSettings->ClipProperties.AudioStreamType ) 978 { 979 case M4VIDEOEDITING_kAMR_NB: 980 pClipCtxt->uiAudioFrameSize = 981 (M4OSA_UInt16)M4VSS3GPP_intGetFrameSize_AMRNB( 982 pClipCtxt->pAudioFramePtr); 983 break; 984 985 case M4VIDEOEDITING_kEVRC: 986 pClipCtxt->uiAudioFrameSize = 987 (M4OSA_UInt16)M4VSS3GPP_intGetFrameSize_EVRC( 988 pClipCtxt->pAudioFramePtr); 989 break; 990 default: 991 break; 992 } 993 994 if( 0 == pClipCtxt->uiAudioFrameSize ) 995 { 996 M4OSA_TRACE3_0( 997 "M4VSS3GPP_intClipReadNextAudioFrame()-AMR: AU frame size == 0,\ 998 returning M4VSS3GPP_ERR_INPUT_AUDIO_CORRUPTED_AMR_AU"); 999 return M4VSS3GPP_ERR_INPUT_AUDIO_CORRUPTED_AU; 1000 } 1001 else if( pClipCtxt->uiAudioFrameSize > pClipCtxt->AudioAU.m_size ) 1002 { 1003 M4OSA_TRACE3_0( 1004 "M4VSS3GPP_intClipReadNextAudioFrame()-AMR: AU frame size greater than AU size!,\ 1005 returning M4VSS3GPP_ERR_INPUT_AUDIO_CORRUPTED_AMR_AU"); 1006 return M4VSS3GPP_ERR_INPUT_AUDIO_CORRUPTED_AU; 1007 } 1008 1009 /** 1010 * Check if the end of the current AU has been reached or not */ 1011 if( ( pClipCtxt->pAudioFramePtr + pClipCtxt->uiAudioFrameSize) 1012 < (pClipCtxt->AudioAU.m_dataAddress + pClipCtxt->AudioAU.m_size) ) 1013 { 1014 pClipCtxt->bAudioFrameAvailable = M4OSA_TRUE; 1015 } 1016 else 1017 { 1018 pClipCtxt->bAudioFrameAvailable = 1019 M4OSA_FALSE; /**< will be used for next call */ 1020 } 1021 } 1022 1023 /* ------------------------- */ 1024 /* ---------- AAC ---------- */ 1025 /* ------------------------- */ 1026 1027 else if( ( M4VIDEOEDITING_kAAC 1028 == pClipCtxt->pSettings->ClipProperties.AudioStreamType) 1029 || (M4VIDEOEDITING_kAACplus 1030 == pClipCtxt->pSettings->ClipProperties.AudioStreamType) 1031 || (M4VIDEOEDITING_keAACplus 1032 == pClipCtxt->pSettings->ClipProperties.AudioStreamType) ) 1033 { 1034 err = pClipCtxt->ShellAPI.m_pReaderDataIt->m_pFctGetNextAu( 1035 pClipCtxt->pReaderContext, 1036 (M4_StreamHandler *)pClipCtxt->pAudioStream, 1037 &pClipCtxt->AudioAU); 1038 1039 if( M4NO_ERROR == err ) 1040 { 1041 pClipCtxt->pAudioFramePtr = pClipCtxt->AudioAU.m_dataAddress; 1042 pClipCtxt->uiAudioFrameSize = 1043 (M4OSA_UInt16)pClipCtxt->AudioAU.m_size; 1044 pClipCtxt->iAudioFrameCts = 1045 (M4OSA_Int32)(pClipCtxt->AudioAU.m_CTS * pClipCtxt->scale_audio 1046 + 0.5); 1047 1048 /* Patch because m_CTS is unfortunately rounded in 3gp reader shell */ 1049 /* (cts is not an integer with frequency 24 kHz for example) */ 1050 pClipCtxt->iAudioFrameCts = ( ( pClipCtxt->iAudioFrameCts 1051 + pClipCtxt->iSilenceFrameDuration / 2) 1052 / pClipCtxt->iSilenceFrameDuration) 1053 * pClipCtxt->iSilenceFrameDuration; 1054 } 1055 else if( M4WAR_NO_MORE_AU == err ) 1056 { 1057 /** 1058 * If there is less audio than the stream duration indicated, 1059 * we return silence at the end of the stream. */ 1060 pClipCtxt->pAudioFramePtr = 1061 (M4OSA_MemAddr8)pClipCtxt->pSilenceFrameData; 1062 pClipCtxt->uiAudioFrameSize = pClipCtxt->uiSilenceFrameSize; 1063 pClipCtxt->iAudioFrameCts += pClipCtxt->iSilenceFrameDuration; 1064 1065 M4OSA_TRACE2_0("a #### silence AU"); 1066 1067 /** 1068 * Return with M4WAR_NO_MORE_AU */ 1069 M4OSA_TRACE3_0( 1070 "M4VSS3GPP_intClipReadNextAudioFrame()-AAC:\ 1071 returning M4WAR_NO_MORE_AU (silence)"); 1072 return M4WAR_NO_MORE_AU; 1073 } 1074 else /**< fatal error */ 1075 { 1076 M4OSA_TRACE3_1( 1077 "M4VSS3GPP_intClipReadNextAudioFrame()-AAC: m_pFctGetNextAu() returns 0x%x", 1078 err); 1079 return err; 1080 } 1081 } 1082 1083 /* --------------------------------- */ 1084 /* ---------- MP3, others ---------- */ 1085 /* --------------------------------- */ 1086 1087 else 1088 { 1089 err = pClipCtxt->ShellAPI.m_pReaderDataIt->m_pFctGetNextAu( 1090 pClipCtxt->pReaderContext, 1091 (M4_StreamHandler *)pClipCtxt->pAudioStream, 1092 &pClipCtxt->AudioAU); 1093 1094 if( M4NO_ERROR != err ) 1095 { 1096 M4OSA_TRACE3_1( 1097 "M4VSS3GPP_intClipReadNextAudioFrame()-MP3: m_pFctGetNextAu() returns 0x%x", 1098 err); 1099 return err; 1100 } 1101 1102 pClipCtxt->pAudioFramePtr = pClipCtxt->AudioAU.m_dataAddress; 1103 pClipCtxt->uiAudioFrameSize = (M4OSA_UInt16)pClipCtxt->AudioAU.m_size; 1104 pClipCtxt->iAudioFrameCts = 1105 (M4OSA_Int32)(pClipCtxt->AudioAU.m_CTS * pClipCtxt->scale_audio 1106 + 0.5); 1107 } 1108 1109 /** 1110 * Return with no error */ 1111 M4OSA_TRACE3_0( 1112 "M4VSS3GPP_intClipReadNextAudioFrame(): returning M4NO_ERROR"); 1113 1114 return M4NO_ERROR; 1115} 1116 1117/** 1118 ****************************************************************************** 1119 * M4OSA_ERR M4VSS3GPP_intClipPrepareAudioDecoder() 1120 * @brief Creates and initialize the audio decoder for the clip. 1121 * @note 1122 * @param pClipCtxt (IN) internal clip context 1123 * @return M4NO_ERROR: No error 1124 ****************************************************************************** 1125 */ 1126static M4OSA_ERR M4VSS3GPP_intClipPrepareAudioDecoder( 1127 M4VSS3GPP_ClipContext *pClipCtxt ) 1128{ 1129 M4OSA_ERR err = M4NO_ERROR; 1130 M4_StreamType audiotype; 1131#ifdef M4VSS_SUPPORT_OMX_CODECS 1132 1133 M4_AACType iAacType = 0; 1134 1135#endif 1136 1137 /** 1138 * Set the proper audio decoder */ 1139 1140 audiotype = pClipCtxt->pAudioStream->m_basicProperties.m_streamType; 1141 1142 //EVRC 1143 if( M4DA_StreamTypeAudioEvrc 1144 != audiotype ) /* decoder not supported yet, but allow to do null encoding */ 1145 1146 err = M4VSS3GPP_setCurrentAudioDecoder(&pClipCtxt->ShellAPI, audiotype); 1147 M4ERR_CHECK_RETURN(err); 1148 1149 /** 1150 * Creates the audio decoder */ 1151 if( M4OSA_NULL == pClipCtxt->ShellAPI.m_pAudioDecoder ) 1152 { 1153 M4OSA_TRACE1_0( 1154 "M4VSS3GPP_intClipPrepareAudioDecoder(): Fails to initiate the audio decoder."); 1155 return M4VSS3GPP_ERR_AUDIO_DECODER_INIT_FAILED; 1156 } 1157 1158 if( M4OSA_NULL == pClipCtxt->pAudioDecCtxt ) 1159 { 1160#ifdef M4VSS_SUPPORT_OMX_CODECS 1161 1162 if( M4OSA_TRUE == pClipCtxt->ShellAPI.bAllowFreeingOMXCodecInterface ) 1163 { 1164 if( M4DA_StreamTypeAudioAac == audiotype ) { 1165 err = M4VSS3GPP_intCheckAndGetCodecAacProperties( 1166 pClipCtxt); 1167 } else if (M4DA_StreamTypeAudioPcm != audiotype) { 1168 err = pClipCtxt->ShellAPI.m_pAudioDecoder->m_pFctCreateAudioDec( 1169 &pClipCtxt->pAudioDecCtxt, pClipCtxt->pAudioStream, 1170 M4OSA_NULL); 1171 } else { 1172 err = M4NO_ERROR; 1173 } 1174 if( M4NO_ERROR != err ) 1175 { 1176 M4OSA_TRACE1_1( 1177 "M4VSS3GPP_intClipPrepareAudioDecoder: m_pAudioDecoder->m_pFctCreateAudioDec\ 1178 returns 0x%x", err); 1179 return err; 1180 } 1181 } 1182 else 1183 { 1184 M4OSA_TRACE3_1( 1185 "M4VSS3GPP_intClipPrepareAudioDecoder:\ 1186 Creating external audio decoder of type 0x%x", audiotype); 1187 /* External OMX codecs are used*/ 1188 if( M4DA_StreamTypeAudioAac == audiotype ) 1189 { 1190 err = pClipCtxt->ShellAPI.m_pAudioDecoder->m_pFctCreateAudioDec( 1191 &pClipCtxt->pAudioDecCtxt, pClipCtxt->pAudioStream, 1192 pClipCtxt->ShellAPI.pCurrentAudioDecoderUserData); 1193 1194 if( M4NO_ERROR == err ) 1195 { 1196 /* AAC properties*/ 1197 /*get from Reader; temporary, till Audio decoder shell API 1198 available to get the AAC properties*/ 1199 pClipCtxt->AacProperties.aNumChan = 1200 pClipCtxt->pAudioStream->m_nbChannels; 1201 pClipCtxt->AacProperties.aSampFreq = 1202 pClipCtxt->pAudioStream->m_samplingFrequency; 1203 1204 err = pClipCtxt->ShellAPI.m_pAudioDecoder-> 1205 m_pFctGetOptionAudioDec(pClipCtxt->pAudioDecCtxt, 1206 M4AD_kOptionID_StreamType, 1207 (M4OSA_DataOption) &iAacType); 1208 1209 if( M4NO_ERROR != err ) 1210 { 1211 M4OSA_TRACE1_1( 1212 "M4VSS3GPP_intClipPrepareAudioDecoder:\ 1213 m_pAudioDecoder->m_pFctGetOptionAudioDec returns err 0x%x", err); 1214 iAacType = M4_kAAC; //set to default 1215 err = M4NO_ERROR; 1216 } 1217 else { 1218 M4OSA_TRACE3_1( 1219 "M4VSS3GPP_intClipPrepareAudioDecoder: \ 1220 m_pAudioDecoder->m_pFctGetOptionAudioDec returns streamType %d", 1221 iAacType); 1222 } 1223 switch( iAacType ) 1224 { 1225 case M4_kAAC: 1226 pClipCtxt->AacProperties.aSBRPresent = 0; 1227 pClipCtxt->AacProperties.aPSPresent = 0; 1228 break; 1229 1230 case M4_kAACplus: 1231 pClipCtxt->AacProperties.aSBRPresent = 1; 1232 pClipCtxt->AacProperties.aPSPresent = 0; 1233 pClipCtxt->AacProperties.aExtensionSampFreq = 1234 pClipCtxt->pAudioStream->m_samplingFrequency; 1235 break; 1236 1237 case M4_keAACplus: 1238 pClipCtxt->AacProperties.aSBRPresent = 1; 1239 pClipCtxt->AacProperties.aPSPresent = 1; 1240 pClipCtxt->AacProperties.aExtensionSampFreq = 1241 pClipCtxt->pAudioStream->m_samplingFrequency; 1242 break; 1243 default: 1244 break; 1245 } 1246 M4OSA_TRACE3_2( 1247 "M4VSS3GPP_intClipPrepareAudioDecoder: AAC NBChans=%d, SamplFreq=%d", 1248 pClipCtxt->AacProperties.aNumChan, 1249 pClipCtxt->AacProperties.aSampFreq); 1250 } 1251 } 1252 else 1253 err = pClipCtxt->ShellAPI.m_pAudioDecoder->m_pFctCreateAudioDec( 1254 &pClipCtxt->pAudioDecCtxt, pClipCtxt->pAudioStream, 1255 pClipCtxt->ShellAPI.pCurrentAudioDecoderUserData); 1256 1257 if( M4NO_ERROR != err ) 1258 { 1259 M4OSA_TRACE1_1( 1260 "M4VSS3GPP_intClipPrepareAudioDecoder:\ 1261 m_pAudioDecoder->m_pFctCreateAudioDec returns 0x%x", 1262 err); 1263 return err; 1264 } 1265 } 1266 1267#else 1268 /* Trick, I use pUserData to retrieve aac properties, 1269 waiting for some better implementation... */ 1270 1271 if( M4DA_StreamTypeAudioAac == audiotype ) 1272 err = pClipCtxt->ShellAPI.m_pAudioDecoder->m_pFctCreateAudioDec( 1273 &pClipCtxt->pAudioDecCtxt, 1274 pClipCtxt->pAudioStream, &(pClipCtxt->AacProperties)); 1275 else 1276 err = pClipCtxt->ShellAPI.m_pAudioDecoder->m_pFctCreateAudioDec( 1277 &pClipCtxt->pAudioDecCtxt, pClipCtxt->pAudioStream, 1278 M4OSA_NULL /* to be changed with HW interfaces */); 1279 1280 if( M4NO_ERROR != err ) 1281 { 1282 M4OSA_TRACE1_1( 1283 "M4VSS3GPP_intClipPrepareAudioDecoder:\ 1284 m_pAudioDecoder->m_pFctCreateAudioDec returns 0x%x", 1285 err); 1286 return err; 1287 } 1288 1289#endif 1290 1291 } 1292 1293 if( M4DA_StreamTypeAudioAmrNarrowBand == audiotype ) { 1294 /* AMR DECODER CONFIGURATION */ 1295 1296 /* nothing specific to do */ 1297 } 1298 else if( M4DA_StreamTypeAudioEvrc == audiotype ) { 1299 /* EVRC DECODER CONFIGURATION */ 1300 1301 /* nothing specific to do */ 1302 } 1303 else if( M4DA_StreamTypeAudioMp3 == audiotype ) { 1304 /* MP3 DECODER CONFIGURATION */ 1305 1306 /* nothing specific to do */ 1307 } 1308 else if( M4DA_StreamTypeAudioAac == audiotype ) 1309 { 1310 /* AAC DECODER CONFIGURATION */ 1311 1312 /* Decode high quality aac but disable PS and SBR */ 1313 /* Because we have to mix different kind of AAC so we must take the lowest capability */ 1314 /* In MCS it was not needed because there is only one stream */ 1315 M4_AacDecoderConfig AacDecParam; 1316 1317 AacDecParam.m_AACDecoderProfile = AAC_kAAC; 1318 AacDecParam.m_DownSamplingMode = AAC_kDS_OFF; 1319 1320 if( M4ENCODER_kMono == pClipCtxt->pAudioStream->m_nbChannels ) 1321 { 1322 AacDecParam.m_OutputMode = AAC_kMono; 1323 } 1324 else 1325 { 1326 AacDecParam.m_OutputMode = AAC_kStereo; 1327 } 1328 1329 err = pClipCtxt->ShellAPI.m_pAudioDecoder->m_pFctSetOptionAudioDec( 1330 pClipCtxt->pAudioDecCtxt, 1331 M4AD_kOptionID_UserParam, (M4OSA_DataOption) &AacDecParam); 1332 } 1333 1334 if( M4OSA_NULL != pClipCtxt->ShellAPI.m_pAudioDecoder->m_pFctSetOptionAudioDec ) { 1335 pClipCtxt->ShellAPI.m_pAudioDecoder->m_pFctSetOptionAudioDec( 1336 pClipCtxt->pAudioDecCtxt, M4AD_kOptionID_3gpReaderInterface, 1337 (M4OSA_DataOption) pClipCtxt->ShellAPI.m_pReaderDataIt); 1338 1339 pClipCtxt->ShellAPI.m_pAudioDecoder->m_pFctSetOptionAudioDec( 1340 pClipCtxt->pAudioDecCtxt, M4AD_kOptionID_AudioAU, 1341 (M4OSA_DataOption) &pClipCtxt->AudioAU); 1342 } 1343 1344 if( M4OSA_NULL != pClipCtxt->ShellAPI.m_pAudioDecoder->m_pFctStartAudioDec ) 1345 { 1346 /* Not implemented in all decoders */ 1347 err = pClipCtxt->ShellAPI.m_pAudioDecoder->m_pFctStartAudioDec( 1348 pClipCtxt->pAudioDecCtxt); 1349 1350 if( M4NO_ERROR != err ) 1351 { 1352 M4OSA_TRACE1_1( 1353 "M4VSS3GPP_intClipPrepareAudioDecoder:\ 1354 m_pAudioDecoder->m_pFctStartAudioDec returns 0x%x", 1355 err); 1356 return err; 1357 } 1358 } 1359 1360 /** 1361 * Allocate output buffer for the audio decoder */ 1362 pClipCtxt->AudioDecBufferOut.m_bufferSize = 1363 pClipCtxt->pAudioStream->m_byteFrameLength 1364 * pClipCtxt->pAudioStream->m_byteSampleSize 1365 * pClipCtxt->pAudioStream->m_nbChannels; 1366 pClipCtxt->AudioDecBufferOut.m_dataAddress = 1367 (M4OSA_MemAddr8)M4OSA_32bitAlignedMalloc(pClipCtxt->AudioDecBufferOut.m_bufferSize 1368 * sizeof(M4OSA_Int16), 1369 M4VSS3GPP, (M4OSA_Char *)"AudioDecBufferOut.m_bufferSize"); 1370 1371 if( M4OSA_NULL == pClipCtxt->AudioDecBufferOut.m_dataAddress ) 1372 { 1373 M4OSA_TRACE1_0( 1374 "M4VSS3GPP_intClipPrepareAudioDecoder():\ 1375 unable to allocate AudioDecBufferOut.m_dataAddress, returning M4ERR_ALLOC"); 1376 return M4ERR_ALLOC; 1377 } 1378 1379 return M4NO_ERROR; 1380} 1381 1382/** 1383 ****************************************************************************** 1384 * M4OSA_ERR M4VSS3GPP_intClipDecodeCurrentAudioFrame() 1385 * @brief Decode the current AUDIO frame. 1386 * @note 1387 * @param pClipCtxt (IN) internal clip context 1388 * @return M4NO_ERROR: No error 1389 ****************************************************************************** 1390 */ 1391M4OSA_ERR M4VSS3GPP_intClipDecodeCurrentAudioFrame( 1392 M4VSS3GPP_ClipContext *pClipCtxt ) 1393{ 1394 M4OSA_ERR err; 1395 1396 /** 1397 * Silence mode */ 1398 if( pClipCtxt->pSilenceFrameData 1399 == (M4OSA_UInt8 *)pClipCtxt->pAudioFramePtr ) 1400 { 1401 if( pClipCtxt->AudioDecBufferOut.m_dataAddress == M4OSA_NULL ) 1402 { 1403 /** 1404 * Allocate output buffer for the audio decoder */ 1405 pClipCtxt->AudioDecBufferOut.m_bufferSize = 1406 pClipCtxt->uiSilencePcmSize; 1407 pClipCtxt->AudioDecBufferOut.m_dataAddress = 1408 (M4OSA_MemAddr8)M4OSA_32bitAlignedMalloc( 1409 pClipCtxt->AudioDecBufferOut.m_bufferSize 1410 * sizeof(M4OSA_Int16), 1411 M4VSS3GPP,(M4OSA_Char *) "AudioDecBufferOut.m_bufferSize"); 1412 1413 if( M4OSA_NULL == pClipCtxt->AudioDecBufferOut.m_dataAddress ) 1414 { 1415 M4OSA_TRACE1_0( 1416 "M4VSS3GPP_intClipDecodeCurrentAudioFrame():\ 1417 unable to allocate AudioDecBufferOut.m_dataAddress, returning M4ERR_ALLOC"); 1418 return M4ERR_ALLOC; 1419 } 1420 } 1421 1422 /* Fill it with 0 (= pcm silence) */ 1423 memset(pClipCtxt->AudioDecBufferOut.m_dataAddress,0, 1424 pClipCtxt->AudioDecBufferOut.m_bufferSize * sizeof(M4OSA_Int16)); 1425 } 1426 else if (pClipCtxt->pSettings->FileType == M4VIDEOEDITING_kFileType_PCM) 1427 { 1428 pClipCtxt->AudioDecBufferIn.m_dataAddress = (M4OSA_MemAddr8) pClipCtxt->pAudioFramePtr; 1429 pClipCtxt->AudioDecBufferIn.m_bufferSize = pClipCtxt->uiAudioFrameSize; 1430 1431 memcpy((void *)pClipCtxt->AudioDecBufferOut.m_dataAddress, 1432 (void *)pClipCtxt->AudioDecBufferIn.m_dataAddress, pClipCtxt->AudioDecBufferIn.m_bufferSize); 1433 pClipCtxt->AudioDecBufferOut.m_bufferSize = pClipCtxt->AudioDecBufferIn.m_bufferSize; 1434 /** 1435 * Return with no error */ 1436 1437 M4OSA_TRACE3_0("M4VSS3GPP_intClipDecodeCurrentAudioFrame(): returning M4NO_ERROR"); 1438 return M4NO_ERROR; 1439 } 1440 /** 1441 * Standard decoding mode */ 1442 else 1443 { 1444 /** 1445 * Decode current AMR frame */ 1446 if ( pClipCtxt->pAudioFramePtr != M4OSA_NULL ) { 1447 pClipCtxt->AudioDecBufferIn.m_dataAddress = 1448 (M4OSA_MemAddr8)pClipCtxt->pAudioFramePtr; 1449 pClipCtxt->AudioDecBufferIn.m_bufferSize = 1450 pClipCtxt->uiAudioFrameSize; 1451 pClipCtxt->AudioDecBufferIn.m_timeStampUs = 1452 (int64_t) (pClipCtxt->iAudioFrameCts * 1000LL); 1453 1454 err = pClipCtxt->ShellAPI.m_pAudioDecoder->m_pFctStepAudioDec( 1455 pClipCtxt->pAudioDecCtxt, 1456 &pClipCtxt->AudioDecBufferIn, &pClipCtxt->AudioDecBufferOut, 1457 M4OSA_FALSE); 1458 } else { 1459 // Pass Null input buffer 1460 // Reader invoked from Audio decoder source 1461 err = pClipCtxt->ShellAPI.m_pAudioDecoder->m_pFctStepAudioDec( 1462 pClipCtxt->pAudioDecCtxt, 1463 M4OSA_NULL, &pClipCtxt->AudioDecBufferOut, 1464 M4OSA_FALSE); 1465 } 1466 1467 if( M4NO_ERROR != err ) 1468 { 1469 M4OSA_TRACE1_1( 1470 "M4VSS3GPP_intClipDecodeCurrentAudioFrame():\ 1471 m_pAudioDecoder->m_pFctStepAudio returns 0x%x", 1472 err); 1473 return err; 1474 } 1475 } 1476 1477 /** 1478 * Return with no error */ 1479 M4OSA_TRACE3_0( 1480 "M4VSS3GPP_intClipDecodeCurrentAudioFrame(): returning M4NO_ERROR"); 1481 return M4NO_ERROR; 1482} 1483 1484/** 1485 ****************************************************************************** 1486 * M4OSA_ERR M4VSS3GPP_intClipJumpAudioAt() 1487 * @brief Jump in the audio track of the clip. 1488 * @note 1489 * @param pClipCtxt (IN) internal clip context 1490 * @param pJumpCts (IN/OUT) in:target CTS, out: reached CTS 1491 * @return M4NO_ERROR: No error 1492 ****************************************************************************** 1493 */ 1494M4OSA_ERR M4VSS3GPP_intClipJumpAudioAt( M4VSS3GPP_ClipContext *pClipCtxt, 1495 M4OSA_Int32 *pJumpCts ) 1496{ 1497 M4OSA_ERR err; 1498 M4OSA_Int32 iTargetCts; 1499 M4OSA_Int32 iJumpCtsMs; 1500 1501 /** 1502 * Check input parameters */ 1503 M4OSA_DEBUG_IF2((M4OSA_NULL == pClipCtxt), M4ERR_PARAMETER, 1504 "M4VSS3GPP_intClipJumpAudioAt: pClipCtxt is M4OSA_NULL"); 1505 M4OSA_DEBUG_IF2((M4OSA_NULL == pJumpCts), M4ERR_PARAMETER, 1506 "M4VSS3GPP_intClipJumpAudioAt: pJumpCts is M4OSA_NULL"); 1507 1508 iTargetCts = *pJumpCts; 1509 1510 /** 1511 * If there is no audio stream, we simulate a jump at the target jump CTS */ 1512 if( M4OSA_NULL == pClipCtxt->pAudioStream ) 1513 { 1514 /** 1515 * the target CTS will be reached at next ReadFrame call (thus the -20) */ 1516 *pJumpCts = iTargetCts - pClipCtxt->iSilenceFrameDuration; 1517 1518 /* Patch because m_CTS is unfortunately rounded in 3gp reader shell */ 1519 /* (cts is not an integer with frequency 24 kHz for example) */ 1520 *pJumpCts = ( ( *pJumpCts + pClipCtxt->iSilenceFrameDuration / 2) 1521 / pClipCtxt->iSilenceFrameDuration) 1522 * pClipCtxt->iSilenceFrameDuration; 1523 pClipCtxt->iAudioFrameCts = 1524 * 1525 pJumpCts; /* simulate a read at jump position for later silence AUs */ 1526 } 1527 else 1528 { 1529 M4OSA_Int32 current_time = 0; 1530 M4OSA_Int32 loop_counter = 0; 1531 1532 if( (M4DA_StreamTypeAudioMp3 1533 == pClipCtxt->pAudioStream->m_basicProperties.m_streamType) ) 1534 { 1535 while( ( loop_counter < M4VSS3GPP_MP3_JUMPED_AU_NUMBER_MAX) 1536 && (current_time < iTargetCts) ) 1537 { 1538 err = pClipCtxt->ShellAPI.m_pReaderDataIt->m_pFctGetNextAu( 1539 pClipCtxt->pReaderContext, 1540 (M4_StreamHandler *)pClipCtxt->pAudioStream, 1541 &pClipCtxt->AudioAU); 1542 1543 if( M4NO_ERROR != err ) 1544 { 1545 M4OSA_TRACE3_1( 1546 "M4VSS3GPP_intClipJumpAudioAt: m_pFctGetNextAu() returns 0x%x", 1547 err); 1548 return err; 1549 } 1550 1551 current_time = (M4OSA_Int32)pClipCtxt->AudioAU.m_CTS; 1552 loop_counter++; 1553 } 1554 1555 /** 1556 * The current AU is stored */ 1557 pClipCtxt->pAudioFramePtr = pClipCtxt->AudioAU.m_dataAddress; 1558 pClipCtxt->uiAudioFrameSize = 1559 (M4OSA_UInt16)pClipCtxt->AudioAU.m_size; 1560 pClipCtxt->iAudioFrameCts = 1561 (M4OSA_Int32)(pClipCtxt->AudioAU.m_CTS * pClipCtxt->scale_audio 1562 + 0.5); 1563 1564 *pJumpCts = pClipCtxt->iAudioFrameCts; 1565 } 1566 else 1567 { 1568 /** 1569 * Jump in the audio stream */ 1570 iJumpCtsMs = 1571 (M4OSA_Int32)(*pJumpCts / pClipCtxt->scale_audio + 0.5); 1572 1573 err = pClipCtxt->ShellAPI.m_pReader->m_pFctJump( 1574 pClipCtxt->pReaderContext, 1575 (M4_StreamHandler *)pClipCtxt->pAudioStream, 1576 &iJumpCtsMs); 1577 1578 if( M4NO_ERROR != err ) 1579 { 1580 M4OSA_TRACE1_1( 1581 "M4VSS3GPP_intClipJumpAudioAt(): m_pFctJump() returns 0x%x", 1582 err); 1583 return err; 1584 } 1585 1586 *pJumpCts = 1587 (M4OSA_Int32)(iJumpCtsMs * pClipCtxt->scale_audio + 0.5); 1588 1589 /* Patch because m_CTS is unfortunately rounded in 3gp reader shell */ 1590 /* (cts is not an integer with frequency 24 kHz for example) */ 1591 *pJumpCts = ( ( *pJumpCts + pClipCtxt->iSilenceFrameDuration / 2) 1592 / pClipCtxt->iSilenceFrameDuration) 1593 * pClipCtxt->iSilenceFrameDuration; 1594 pClipCtxt->iAudioFrameCts = 0; /* No frame read yet */ 1595 1596 /** 1597 * To detect some may-be bugs, I prefer to reset all these after a jump */ 1598 pClipCtxt->bAudioFrameAvailable = M4OSA_FALSE; 1599 pClipCtxt->pAudioFramePtr = M4OSA_NULL; 1600 1601 /** 1602 * In AMR, we have to manage multi-framed AUs, 1603 but also in AAC the jump can be 1 AU too much backward */ 1604 if( *pJumpCts < iTargetCts ) 1605 { 1606 /** 1607 * Jump doesn't read any AU, we must read at least one */ 1608 err = M4VSS3GPP_intClipReadNextAudioFrame(pClipCtxt); 1609 1610 if( M4OSA_ERR_IS_ERROR(err) ) 1611 { 1612 M4OSA_TRACE1_1( 1613 "M4VSS3GPP_intClipJumpAudioAt():\ 1614 M4VSS3GPP_intClipReadNextAudioFrame(a) returns 0x%x", 1615 err); 1616 return err; 1617 } 1618 1619 /** 1620 * Read AU frames as long as we reach the AU before the target CTS 1621 * (so the target will be reached when the user call ReadNextAudioFrame). */ 1622 while( pClipCtxt->iAudioFrameCts 1623 < (iTargetCts - pClipCtxt->iSilenceFrameDuration) ) 1624 { 1625 err = M4VSS3GPP_intClipReadNextAudioFrame(pClipCtxt); 1626 1627 if( M4OSA_ERR_IS_ERROR(err) ) 1628 { 1629 M4OSA_TRACE1_1( 1630 "M4VSS3GPP_intClipJumpAudioAt():\ 1631 M4VSS3GPP_intClipReadNextAudioFrame(b) returns 0x%x", 1632 err); 1633 return err; 1634 } 1635 } 1636 1637 /** 1638 * Return the CTS that will be reached at next ReadFrame */ 1639 *pJumpCts = pClipCtxt->iAudioFrameCts 1640 + pClipCtxt->iSilenceFrameDuration; 1641 } 1642 } 1643 } 1644 1645 /** 1646 * Return with no error */ 1647 M4OSA_TRACE3_0("M4VSS3GPP_intClipJumpAudioAt(): returning M4NO_ERROR"); 1648 return M4NO_ERROR; 1649} 1650 1651/** 1652 ****************************************************************************** 1653 * M4OSA_ERR M4VSS3GPP_intClipClose() 1654 * @brief Close a clip. Destroy the context. 1655 * @note 1656 * @param pClipCtxt (IN) Internal clip context 1657 * @return M4NO_ERROR: No error 1658 ****************************************************************************** 1659 */ 1660M4OSA_ERR M4VSS3GPP_intClipClose( M4VSS3GPP_ClipContext *pClipCtxt ) 1661{ 1662 M4OSA_ERR err; 1663 1664 /** 1665 * Check input parameters */ 1666 M4OSA_DEBUG_IF2((M4OSA_NULL == pClipCtxt), M4ERR_PARAMETER, 1667 "M4VSS3GPP_intClipClose: pClipCtxt is M4OSA_NULL"); 1668 1669 /** 1670 * Free the video decoder context */ 1671 if( M4OSA_NULL != pClipCtxt->pViDecCtxt ) 1672 { 1673 pClipCtxt->ShellAPI.m_pVideoDecoder->m_pFctDestroy( 1674 pClipCtxt->pViDecCtxt); 1675 pClipCtxt->pViDecCtxt = M4OSA_NULL; 1676 } 1677 1678 /** 1679 * Free the audio decoder context */ 1680 if( M4OSA_NULL != pClipCtxt->pAudioDecCtxt ) 1681 { 1682 err = pClipCtxt->ShellAPI.m_pAudioDecoder->m_pFctDestroyAudioDec( 1683 pClipCtxt->pAudioDecCtxt); 1684 1685 if( M4NO_ERROR != err ) 1686 { 1687 M4OSA_TRACE1_1( 1688 "M4VSS3GPP_intClipClose: m_pAudioDecoder->m_pFctDestroyAudioDec returns 0x%x", 1689 err); 1690 /**< don't return, we still have stuff to free */ 1691 } 1692 1693 pClipCtxt->pAudioDecCtxt = M4OSA_NULL; 1694 } 1695 1696 /** 1697 * Free the decoded audio buffer */ 1698 if( M4OSA_NULL != pClipCtxt->AudioDecBufferOut.m_dataAddress ) 1699 { 1700 free(pClipCtxt->AudioDecBufferOut.m_dataAddress); 1701 pClipCtxt->AudioDecBufferOut.m_dataAddress = M4OSA_NULL; 1702 } 1703 1704 /** 1705 * Audio AU is allocated by reader. 1706 * If no audio track, audio AU is set at 'silent' (SID) by VSS. 1707 * As a consequence, if audio AU is set to 'silent' (static) 1708 it can't be free unless it is set to NULL */ 1709 if( ( (M4OSA_MemAddr8)M4VSS3GPP_AMR_AU_SILENCE_FRAME_048 1710 == pClipCtxt->AudioAU.m_dataAddress) 1711 || ((M4OSA_MemAddr8)pClipCtxt->pSilenceFrameData 1712 == pClipCtxt->AudioAU.m_dataAddress) ) 1713 { 1714 pClipCtxt->AudioAU.m_dataAddress = M4OSA_NULL; 1715 } 1716 1717 if( M4OSA_NULL != pClipCtxt->pReaderContext ) 1718 { 1719 /** 1720 * Close the 3GPP or MP3 reader */ 1721 err = pClipCtxt->ShellAPI.m_pReader->m_pFctClose( 1722 pClipCtxt->pReaderContext); 1723 1724 if( M4NO_ERROR != err ) 1725 { 1726 M4OSA_TRACE1_1( 1727 "M4VSS3GPP_intClipClose(): m_pReader->m_pFctClose returns 0x%x", 1728 err); 1729 } 1730 1731 /** 1732 * Destroy the 3GPP or MP3 reader context */ 1733 err = pClipCtxt->ShellAPI.m_pReader->m_pFctDestroy( 1734 pClipCtxt->pReaderContext); 1735 1736 if( M4NO_ERROR != err ) 1737 { 1738 M4OSA_TRACE1_1( 1739 "M4VSS3GPP_intClipClose(): m_pReader->m_pFctDestroy returns 0x%x", 1740 err); 1741 } 1742 1743 pClipCtxt->pReaderContext = M4OSA_NULL; 1744 } 1745 1746 /** 1747 * Return with no error */ 1748 M4OSA_TRACE3_1("M4VSS3GPP_intClipClose(Ctxt=0x%x): returning M4NO_ERROR", 1749 pClipCtxt); 1750 return M4NO_ERROR; 1751} 1752 1753M4OSA_ERR M4VSS3GPP_intClipCleanUp( M4VSS3GPP_ClipContext *pClipCtxt ) 1754{ 1755 M4OSA_ERR err = M4NO_ERROR, err2; 1756 1757 /** 1758 * Check input parameters */ 1759 M4OSA_DEBUG_IF2((M4OSA_NULL == pClipCtxt), M4ERR_PARAMETER, 1760 "M4VSS3GPP_intClipCleanUp: pClipCtxt is M4OSA_NULL"); 1761 1762 /** 1763 * Free the video decoder context */ 1764 if( M4OSA_NULL != pClipCtxt->pViDecCtxt ) 1765 { 1766 pClipCtxt->ShellAPI.m_pVideoDecoder->m_pFctDestroy( 1767 pClipCtxt->pViDecCtxt); 1768 pClipCtxt->pViDecCtxt = M4OSA_NULL; 1769 } 1770 1771 /** 1772 * Free the audio decoder context */ 1773 if( M4OSA_NULL != pClipCtxt->pAudioDecCtxt ) 1774 { 1775 err2 = pClipCtxt->ShellAPI.m_pAudioDecoder->m_pFctDestroyAudioDec( 1776 pClipCtxt->pAudioDecCtxt); 1777 1778 if( M4NO_ERROR != err2 ) 1779 { 1780 M4OSA_TRACE1_1( 1781 "M4VSS3GPP_intClipCleanUp: m_pAudioDecoder->m_pFctDestroyAudioDec returns 0x%x", 1782 err); 1783 /**< don't return, we still have stuff to free */ 1784 if( M4NO_ERROR != err ) 1785 err = err2; 1786 } 1787 1788 pClipCtxt->pAudioDecCtxt = M4OSA_NULL; 1789 } 1790 1791 /** 1792 * Free the decoded audio buffer */ 1793 if( M4OSA_NULL != pClipCtxt->AudioDecBufferOut.m_dataAddress ) 1794 { 1795 free(pClipCtxt->AudioDecBufferOut.m_dataAddress); 1796 pClipCtxt->AudioDecBufferOut.m_dataAddress = M4OSA_NULL; 1797 } 1798 1799 /** 1800 * Audio AU is allocated by reader. 1801 * If no audio track, audio AU is set at 'silent' (SID) by VSS. 1802 * As a consequence, if audio AU is set to 'silent' (static) 1803 it can't be free unless it is set to NULL */ 1804 if( ( (M4OSA_MemAddr8)M4VSS3GPP_AMR_AU_SILENCE_FRAME_048 1805 == pClipCtxt->AudioAU.m_dataAddress) 1806 || ((M4OSA_MemAddr8)pClipCtxt->pSilenceFrameData 1807 == pClipCtxt->AudioAU.m_dataAddress) ) 1808 { 1809 pClipCtxt->AudioAU.m_dataAddress = M4OSA_NULL; 1810 } 1811 1812 if( M4OSA_NULL != pClipCtxt->pReaderContext ) 1813 { 1814 /** 1815 * Close the 3GPP or MP3 reader */ 1816 err2 = pClipCtxt->ShellAPI.m_pReader->m_pFctClose( 1817 pClipCtxt->pReaderContext); 1818 1819 if( M4NO_ERROR != err2 ) 1820 { 1821 M4OSA_TRACE1_1( 1822 "M4VSS3GPP_intClipCleanUp(): m_pReader->m_pFctClose returns 0x%x", 1823 err); 1824 1825 if( M4NO_ERROR != err ) 1826 err = err2; 1827 } 1828 1829 /** 1830 * Destroy the 3GPP or MP3 reader context */ 1831 err2 = pClipCtxt->ShellAPI.m_pReader->m_pFctDestroy( 1832 pClipCtxt->pReaderContext); 1833 1834 if( M4NO_ERROR != err2 ) 1835 { 1836 M4OSA_TRACE1_1( 1837 "M4VSS3GPP_intClipCleanUp(): m_pReader->m_pFctDestroy returns 0x%x", 1838 err); 1839 1840 if( M4NO_ERROR != err ) 1841 err = err2; 1842 } 1843 1844 pClipCtxt->pReaderContext = M4OSA_NULL; 1845 } 1846 1847 if(pClipCtxt->pPlaneYuv != M4OSA_NULL) { 1848 if(pClipCtxt->pPlaneYuv[0].pac_data != M4OSA_NULL) { 1849 free(pClipCtxt->pPlaneYuv[0].pac_data); 1850 pClipCtxt->pPlaneYuv[0].pac_data = M4OSA_NULL; 1851 } 1852 free(pClipCtxt->pPlaneYuv); 1853 pClipCtxt->pPlaneYuv = M4OSA_NULL; 1854 } 1855 1856 if(pClipCtxt->pPlaneYuvWithEffect != M4OSA_NULL) { 1857 if(pClipCtxt->pPlaneYuvWithEffect[0].pac_data != M4OSA_NULL) { 1858 free(pClipCtxt->pPlaneYuvWithEffect[0].pac_data); 1859 pClipCtxt->pPlaneYuvWithEffect[0].pac_data = M4OSA_NULL; 1860 } 1861 free(pClipCtxt->pPlaneYuvWithEffect); 1862 pClipCtxt->pPlaneYuvWithEffect = M4OSA_NULL; 1863 } 1864 /** 1865 * Free the shells interfaces */ 1866 M4VSS3GPP_unRegisterAllWriters(&pClipCtxt->ShellAPI); 1867 M4VSS3GPP_unRegisterAllEncoders(&pClipCtxt->ShellAPI); 1868 M4VSS3GPP_unRegisterAllReaders(&pClipCtxt->ShellAPI); 1869 M4VSS3GPP_unRegisterAllDecoders(&pClipCtxt->ShellAPI); 1870 1871 M4OSA_TRACE3_1("M4VSS3GPP_intClipCleanUp: pClipCtxt=0x%x", pClipCtxt); 1872 /** 1873 * Free the clip context */ 1874 free(pClipCtxt); 1875 1876 return err; 1877} 1878 1879/** 1880 ****************************************************************************** 1881 * M4OSA_UInt32 M4VSS3GPP_intGetFrameSize_AMRNB() 1882 * @brief Return the length, in bytes, of the AMR Narrow-Band frame contained in the given buffer 1883 * @note 1884 * @param pAudioFrame (IN) AMRNB frame 1885 * @return M4NO_ERROR: No error 1886 ****************************************************************************** 1887 */ 1888 1889M4OSA_UInt32 M4VSS3GPP_intGetFrameSize_AMRNB( M4OSA_MemAddr8 pAudioFrame ) 1890{ 1891 M4OSA_UInt32 frameSize = 0; 1892 M4OSA_UInt32 frameType = ( ( *pAudioFrame) &(0xF << 3)) >> 3; 1893 1894 switch( frameType ) 1895 { 1896 case 0: 1897 frameSize = 95; 1898 break; /* 4750 bps */ 1899 1900 case 1: 1901 frameSize = 103; 1902 break; /* 5150 bps */ 1903 1904 case 2: 1905 frameSize = 118; 1906 break; /* 5900 bps */ 1907 1908 case 3: 1909 frameSize = 134; 1910 break; /* 6700 bps */ 1911 1912 case 4: 1913 frameSize = 148; 1914 break; /* 7400 bps */ 1915 1916 case 5: 1917 frameSize = 159; 1918 break; /* 7950 bps */ 1919 1920 case 6: 1921 frameSize = 204; 1922 break; /* 10200 bps */ 1923 1924 case 7: 1925 frameSize = 244; 1926 break; /* 12000 bps */ 1927 1928 case 8: 1929 frameSize = 39; 1930 break; /* SID (Silence) */ 1931 1932 case 15: 1933 frameSize = 0; 1934 break; /* No data */ 1935 1936 default: 1937 M4OSA_TRACE3_0( 1938 "M4VSS3GPP_intGetFrameSize_AMRNB(): Corrupted AMR frame! returning 0."); 1939 return 0; 1940 } 1941 1942 return (1 + (( frameSize + 7) / 8)); 1943} 1944 1945/** 1946 ****************************************************************************** 1947 * M4OSA_UInt32 M4VSS3GPP_intGetFrameSize_EVRC() 1948 * @brief Return the length, in bytes, of the EVRC frame contained in the given buffer 1949 * @note 1950 * 0 1 2 3 1951 * +-+-+-+-+ 1952 * |fr type| RFC 3558 1953 * +-+-+-+-+ 1954 * 1955 * Frame Type: 4 bits 1956 * The frame type indicates the type of the corresponding codec data 1957 * frame in the RTP packet. 1958 * 1959 * For EVRC and SMV codecs, the frame type values and size of the 1960 * associated codec data frame are described in the table below: 1961 * 1962 * Value Rate Total codec data frame size (in octets) 1963 * --------------------------------------------------------- 1964 * 0 Blank 0 (0 bit) 1965 * 1 1/8 2 (16 bits) 1966 * 2 1/4 5 (40 bits; not valid for EVRC) 1967 * 3 1/2 10 (80 bits) 1968 * 4 1 22 (171 bits; 5 padded at end with zeros) 1969 * 5 Erasure 0 (SHOULD NOT be transmitted by sender) 1970 * 1971 * @param pCpAudioFrame (IN) EVRC frame 1972 * @return M4NO_ERROR: No error 1973 ****************************************************************************** 1974 */ 1975M4OSA_UInt32 M4VSS3GPP_intGetFrameSize_EVRC( M4OSA_MemAddr8 pAudioFrame ) 1976{ 1977 M4OSA_UInt32 frameSize = 0; 1978 M4OSA_UInt32 frameType = ( *pAudioFrame) &0x0F; 1979 1980 switch( frameType ) 1981 { 1982 case 0: 1983 frameSize = 0; 1984 break; /* blank */ 1985 1986 case 1: 1987 frameSize = 16; 1988 break; /* 1/8 */ 1989 1990 case 2: 1991 frameSize = 40; 1992 break; /* 1/4 */ 1993 1994 case 3: 1995 frameSize = 80; 1996 break; /* 1/2 */ 1997 1998 case 4: 1999 frameSize = 171; 2000 break; /* 1 */ 2001 2002 case 5: 2003 frameSize = 0; 2004 break; /* erasure */ 2005 2006 default: 2007 M4OSA_TRACE3_0( 2008 "M4VSS3GPP_intGetFrameSize_EVRC(): Corrupted EVRC frame! returning 0."); 2009 return 0; 2010 } 2011 2012 return (1 + (( frameSize + 7) / 8)); 2013} 2014 2015M4OSA_ERR M4VSS3GPP_intCheckAndGetCodecAacProperties( 2016 M4VSS3GPP_ClipContext *pClipCtxt) { 2017 2018 M4OSA_ERR err = M4NO_ERROR; 2019 M4AD_Buffer outputBuffer; 2020 uint32_t optionValue =0; 2021 2022 // Decode first audio frame from clip to get properties from codec 2023 2024 err = pClipCtxt->ShellAPI.m_pAudioDecoder->m_pFctCreateAudioDec( 2025 &pClipCtxt->pAudioDecCtxt, 2026 pClipCtxt->pAudioStream, &(pClipCtxt->AacProperties)); 2027 2028 pClipCtxt->ShellAPI.m_pAudioDecoder->m_pFctSetOptionAudioDec( 2029 pClipCtxt->pAudioDecCtxt, M4AD_kOptionID_3gpReaderInterface, 2030 (M4OSA_DataOption) pClipCtxt->ShellAPI.m_pReaderDataIt); 2031 2032 pClipCtxt->ShellAPI.m_pAudioDecoder->m_pFctSetOptionAudioDec( 2033 pClipCtxt->pAudioDecCtxt, M4AD_kOptionID_AudioAU, 2034 (M4OSA_DataOption) &pClipCtxt->AudioAU); 2035 2036 if( pClipCtxt->ShellAPI.m_pAudioDecoder->m_pFctStartAudioDec != M4OSA_NULL ) { 2037 2038 err = pClipCtxt->ShellAPI.m_pAudioDecoder->m_pFctStartAudioDec( 2039 pClipCtxt->pAudioDecCtxt); 2040 if( M4NO_ERROR != err ) { 2041 2042 M4OSA_TRACE1_1( 2043 "M4VSS3GPP_intCheckAndGetCodecAacProperties: \ 2044 m_pFctStartAudioDec returns 0x%x", err); 2045 return err; 2046 } 2047 } 2048 2049 /** 2050 * Allocate output buffer for the audio decoder */ 2051 outputBuffer.m_bufferSize = 2052 pClipCtxt->pAudioStream->m_byteFrameLength 2053 * pClipCtxt->pAudioStream->m_byteSampleSize 2054 * pClipCtxt->pAudioStream->m_nbChannels; 2055 2056 if( outputBuffer.m_bufferSize > 0 ) { 2057 2058 outputBuffer.m_dataAddress = 2059 (M4OSA_MemAddr8)M4OSA_32bitAlignedMalloc(outputBuffer.m_bufferSize \ 2060 *sizeof(short), M4VSS3GPP, (M4OSA_Char *)"outputBuffer.m_bufferSize"); 2061 2062 if( M4OSA_NULL == outputBuffer.m_dataAddress ) { 2063 2064 M4OSA_TRACE1_0( 2065 "M4VSS3GPP_intCheckAndGetCodecAacProperties():\ 2066 unable to allocate outputBuffer.m_dataAddress"); 2067 return M4ERR_ALLOC; 2068 } 2069 } 2070 2071 err = pClipCtxt->ShellAPI.m_pAudioDecoder->m_pFctStepAudioDec( 2072 pClipCtxt->pAudioDecCtxt, M4OSA_NULL, &outputBuffer, M4OSA_FALSE); 2073 2074 if ( err == M4WAR_INFO_FORMAT_CHANGE ) { 2075 2076 // Get the properties from codec node 2077 pClipCtxt->ShellAPI.m_pAudioDecoder->m_pFctGetOptionAudioDec( 2078 pClipCtxt->pAudioDecCtxt, 2079 M4AD_kOptionID_AudioNbChannels, (M4OSA_DataOption) &optionValue); 2080 2081 pClipCtxt->AacProperties.aNumChan = optionValue; 2082 // Reset Reader structure value also 2083 pClipCtxt->pAudioStream->m_nbChannels = optionValue; 2084 2085 pClipCtxt->ShellAPI.m_pAudioDecoder->m_pFctGetOptionAudioDec( 2086 pClipCtxt->pAudioDecCtxt, 2087 M4AD_kOptionID_AudioSampFrequency, (M4OSA_DataOption) &optionValue); 2088 2089 pClipCtxt->AacProperties.aSampFreq = optionValue; 2090 // Reset Reader structure value also 2091 pClipCtxt->pAudioStream->m_samplingFrequency = optionValue; 2092 2093 } else if( err != M4NO_ERROR) { 2094 M4OSA_TRACE1_1("M4VSS3GPP_intCheckAndGetCodecAacProperties:\ 2095 m_pFctStepAudioDec returns err = 0x%x", err); 2096 } 2097 2098 free(outputBuffer.m_dataAddress); 2099 2100 // Reset the stream reader 2101 err = pClipCtxt->ShellAPI.m_pReader->m_pFctReset( 2102 pClipCtxt->pReaderContext, 2103 (M4_StreamHandler *)pClipCtxt->pAudioStream); 2104 2105 if (M4NO_ERROR != err) { 2106 M4OSA_TRACE1_1("M4VSS3GPP_intCheckAndGetCodecAacProperties\ 2107 Error in reseting reader: 0x%x", err); 2108 } 2109 2110 return err; 2111 2112} 2113