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 *************************************************************************
19 * @file M4MCS_API.c
20 * @brief MCS implementation (Video Compressor Service)
21 * @note This file implements the API and the processing of the MCS
22 *************************************************************************
23 **/
24
25 /**
26 ********************************************************************
27 * Includes
28 ********************************************************************
29 */
30 /**
31 * OSAL headers */
32 #include "M4OSA_Memory.h" /**< OSAL memory management */
33 #include "M4OSA_Debug.h" /**< OSAL debug management */
34
35 /* PCM samples */
36 #include "VideoEditorResampler.h"
37 /**
38 * Decoder interface */
39 #include "M4DECODER_Common.h"
40
41 /* Encoder interface*/
42 #include "M4ENCODER_common.h"
43
44 /* Enable for DEBUG logging */
45 //#define MCS_DUMP_PCM_TO_FILE
46 #ifdef MCS_DUMP_PCM_TO_FILE
47 #include <stdio.h>
48 FILE *file_au_reader = NULL;
49 FILE *file_pcm_decoder = NULL;
50 FILE *file_pcm_encoder = NULL;
51 #endif
52
53 /* Core headers */
54 #include "M4MCS_API.h"
55 #include "M4MCS_ErrorCodes.h"
56 #include "M4MCS_InternalTypes.h"
57 #include "M4MCS_InternalConfig.h"
58 #include "M4MCS_InternalFunctions.h"
59
60 #ifdef M4MCS_SUPPORT_STILL_PICTURE
61 #include "M4MCS_StillPicture.h"
62 #endif /*M4MCS_SUPPORT_STILL_PICTURE*/
63
64 /* Common headers (for aac) */
65 #include "M4_Common.h"
66
67 #include "NXPSW_CompilerSwitches.h"
68
69 #ifdef M4VSS_ENABLE_EXTERNAL_DECODERS
70 #include "M4VD_EXTERNAL_Interface.h"
71 #endif /* M4VSS_ENABLE_EXTERNAL_DECODERS */
72
73 #include "M4AIR_API.h"
74 #include "OMX_Video.h"
75
76 /* Version */
77 #define M4MCS_VERSION_MAJOR 3
78 #define M4MCS_VERSION_MINOR 4
79 #define M4MCS_VERSION_REVISION 3
80
81 /**
82 ********************************************************************
83 * Static local functions
84 ********************************************************************
85 */
86
87 static M4OSA_ERR M4MCS_intStepSet( M4MCS_InternalContext *pC );
88 static M4OSA_ERR M4MCS_intPrepareVideoDecoder(
89 M4MCS_InternalContext *pC );
90 static M4OSA_ERR M4MCS_intPrepareVideoEncoder(
91 M4MCS_InternalContext *pC );
92 static M4OSA_ERR M4MCS_intPrepareAudioProcessing(
93 M4MCS_InternalContext *pC );
94 static M4OSA_ERR M4MCS_intPrepareWriter( M4MCS_InternalContext *pC );
95 static M4OSA_ERR M4MCS_intPrepareAudioBeginCut(
96 M4MCS_InternalContext *pC );
97 static M4OSA_ERR M4MCS_intStepEncoding(
98 M4MCS_InternalContext *pC,
99 M4OSA_UInt8 *pTranscodedTime );
100 static M4OSA_ERR M4MCS_intStepBeginVideoJump(
101 M4MCS_InternalContext *pC );
102 static M4OSA_ERR M4MCS_intStepBeginVideoDecode(
103 M4MCS_InternalContext *pC );
104 static M4OSA_ERR M4MCS_intAudioNullEncoding( M4MCS_InternalContext *pC );
105 static M4OSA_ERR M4MCS_intAudioTranscoding( M4MCS_InternalContext *pC );
106 static M4OSA_ERR M4MCS_intVideoNullEncoding( M4MCS_InternalContext *pC );
107 static M4OSA_ERR M4MCS_intVideoTranscoding( M4MCS_InternalContext *pC );
108 static M4OSA_ERR M4MCS_intGetInputClipProperties(
109 M4MCS_InternalContext *pContext );
110 static M4OSA_UInt32 M4MCS_intGetFrameSize_AMRNB(
111 M4OSA_MemAddr8 pAudioFrame );
112 static M4OSA_UInt32 M4MCS_intGetFrameSize_EVRC(
113 M4OSA_MemAddr8 pAudioFrame );
114 static M4OSA_ERR M4MCS_intCheckMaxFileSize( M4MCS_Context pContext );
115 static M4VIDEOEDITING_Bitrate M4MCS_intGetNearestBitrate(
116 M4OSA_Int32 freebitrate,
117 M4OSA_Int8 mode );
118 static M4OSA_ERR M4MCS_intCleanUp_ReadersDecoders(
119 M4MCS_InternalContext *pC );
120 static M4OSA_ERR M4MCS_intReallocTemporaryAU(
121 M4OSA_MemAddr8 *addr,
122 M4OSA_UInt32 newSize );
123 static M4OSA_ERR M4MCS_intCheckAndGetCodecProperties(
124 M4MCS_InternalContext *pC);
125
126 static M4OSA_ERR M4MCS_intLimitBitratePerCodecProfileLevel(
127 M4ENCODER_AdvancedParams* EncParams);
128 static M4OSA_Int32 M4MCS_intLimitBitrateForH263Enc(M4OSA_Int32 profile,
129 M4OSA_Int32 level, M4OSA_Int32 bitrate);
130 static M4OSA_Int32 M4MCS_intLimitBitrateForMpeg4Enc(M4OSA_Int32 profile,
131 M4OSA_Int32 level, M4OSA_Int32 bitrate);
132 static M4OSA_Int32 M4MCS_intLimitBitrateForH264Enc(M4OSA_Int32 profile,
133 M4OSA_Int32 level, M4OSA_Int32 bitrate);
134
135 /**
136 **********************************************************************
137 * External function used only by VideoEditor and that does not appear
138 * in the API
139 **********************************************************************
140 */
141
142 M4OSA_ERR M4MCS_open_normalMode( M4MCS_Context pContext,
143 M4OSA_Void *pFileIn,
144 M4VIDEOEDITING_FileType InputFileType,
145 M4OSA_Void *pFileOut,
146 M4OSA_Void *pTempFile );
147
148 /* All errors are fatal in the MCS */
149 #define M4ERR_CHECK_RETURN(err) if(M4NO_ERROR!=err) return err;
150
151 /* A define used with SSRC 1.04 and above to avoid taking blocks smaller
152 * that the minimal block size
153 */
154 #define M4MCS_SSRC_MINBLOCKSIZE 100
155
156 static M4OSA_UChar Tab_MCS[8] =
157 {
158 17, 5, 3, 3, 1, 1, 1, 1
159 };
160
H264MCS_Getinstance(NSWAVC_MCS_t ** instance)161 M4OSA_ERR H264MCS_Getinstance( NSWAVC_MCS_t ** instance )
162 {
163 NSWAVC_MCS_t *p_bs = M4OSA_NULL;
164 M4OSA_ERR err = M4NO_ERROR;
165 p_bs = (NSWAVC_MCS_t *)M4OSA_32bitAlignedMalloc(sizeof(NSWAVC_MCS_t), M4MCS,
166 (M4OSA_Char *)"NSWAVC_MCS_t");
167
168 if( M4OSA_NULL == p_bs )
169 {
170 M4OSA_TRACE1_0("H264MCS_Getinstance: allocation error");
171 return M4ERR_ALLOC;
172 }
173
174 p_bs->prev_frame_num = 0;
175 p_bs->cur_frame_num = 0;
176 p_bs->log2_max_frame_num_minus4 = 0;
177 p_bs->prev_new_frame_num = 0;
178 p_bs->is_done = 0;
179 p_bs->is_first = 1;
180
181 p_bs->m_pDecoderSpecificInfo = M4OSA_NULL;
182 p_bs->m_decoderSpecificInfoSize = 0;
183
184 p_bs->m_pEncoderSPS = M4OSA_NULL;
185 p_bs->m_encoderSPSSize = 0;
186
187 p_bs->m_pEncoderPPS = M4OSA_NULL;
188 p_bs->m_encoderPPSSize = 0;
189
190 p_bs->m_pFinalDSI = M4OSA_NULL;
191 p_bs->m_pFinalDSISize = 0;
192
193 p_bs->p_clip_sps = M4OSA_NULL;
194 p_bs->m_encoder_SPS_Cnt = 0;
195
196 p_bs->p_clip_pps = M4OSA_NULL;
197 p_bs->m_encoder_PPS_Cnt = 0;
198
199 p_bs->p_encoder_sps = M4OSA_NULL;
200 p_bs->p_encoder_pps = M4OSA_NULL;
201
202 p_bs->encoder_pps.slice_group_id = M4OSA_NULL;
203
204 *instance = (NSWAVC_MCS_t *)p_bs;
205 return err;
206 }
207
H264MCS_getBits(ComBitStreamMCS_t * p_bs,M4OSA_UInt32 numBits)208 M4OSA_UInt32 H264MCS_getBits( ComBitStreamMCS_t *p_bs, M4OSA_UInt32 numBits )
209 {
210 M4OSA_UInt32 ui32RetBits;
211 M4OSA_UInt8 *pbs;
212 M4OSA_Int32 bcnt;
213 p_bs->i8BitCnt -= numBits;
214 bcnt = p_bs->i8BitCnt;
215
216 /* Measure the quantity of bits to be read in ui32TempBuff */
217 ui32RetBits = p_bs->ui32TempBuff >> (32 - numBits);
218
219 /* Read numBits in ui32TempBuff */
220 p_bs->ui32TempBuff <<= numBits;
221 p_bs->bitPos += numBits;
222
223 if( bcnt > 24 )
224 {
225 return (ui32RetBits);
226 }
227 else
228 { /* at least one byte can be buffered in ui32TempBuff */
229 pbs = (M4OSA_UInt8 *)p_bs->pui8BfrPtr;
230
231 if( bcnt < (int)(p_bs->numBitsInBuffer - p_bs->bitPos) )
232 { /* not enough remaining bits in ui32TempBuff: need to be filled */
233 do
234 {
235 /* On the fly detection of EPB byte */
236 if( ( *(pbs) == 0x03)
237 && (!(( pbs[-1])
238 | (pbs[-2])))) //(p_bs->ui32LastTwoBytes & 0x0000FFFF) == 0)
239 {
240 /* EPB byte found: skip it and update bitPos accordingly */
241 (pbs)++;
242 p_bs->bitPos += 8;
243 }
244
245 p_bs->ui32TempBuff |= *(pbs)++ << (24 - bcnt);
246 bcnt += 8;
247 } while ( bcnt <= 24 );
248
249 p_bs->pui8BfrPtr = (M4OSA_Int8 *)pbs;
250 p_bs->i8BitCnt = bcnt;
251 return (ui32RetBits);
252 }
253 }
254
255 if( p_bs->bitPos <= p_bs->numBitsInBuffer )
256 {
257 return (ui32RetBits);
258 }
259 else
260 {
261 return (0);
262 }
263 }
264
H264MCS_flushBits(ComBitStreamMCS_t * p_bs,M4OSA_UInt32 numBits)265 M4OSA_Void H264MCS_flushBits( ComBitStreamMCS_t *p_bs, M4OSA_UInt32 numBits )
266 {
267 M4OSA_UInt8 *pbs;
268 M4OSA_UInt32 bcnt;
269 p_bs->i8BitCnt -= numBits;
270 bcnt = p_bs->i8BitCnt;
271
272 p_bs->ui32TempBuff <<= numBits;
273 p_bs->bitPos += numBits;
274
275 if( bcnt > 24 )
276 {
277 return;
278 }
279 else
280 { /* at least one byte can be buffered in ui32TempBuff */
281 pbs = (M4OSA_UInt8 *)p_bs->pui8BfrPtr;
282
283 if( bcnt < (p_bs->numBitsInBuffer - p_bs->bitPos) )
284 { /* Not enough remaining bits in ui32TempBuff: need to be filled */
285 do
286 {
287 /* On the fly detection of EPB byte */
288 if( ( *(pbs) == 0x03) && (!(( pbs[-1]) | (pbs[-2]))) )
289 { /* JC: EPB byte found: skip it and update bitPos accordingly */
290 (pbs)++;
291 p_bs->bitPos += 8;
292 }
293 p_bs->ui32TempBuff |= *(pbs)++ << (24 - bcnt);
294 bcnt += 8;
295 } while ( bcnt <= 24 );
296
297 p_bs->pui8BfrPtr = (M4OSA_Int8 *)pbs;
298 p_bs->i8BitCnt = bcnt;
299 }
300 }
301
302 return;
303 }
304
H264MCS_DecVLCReadExpGolombCode(ComBitStreamMCS_t * p_bs)305 M4OSA_UInt32 H264MCS_DecVLCReadExpGolombCode( ComBitStreamMCS_t *p_bs )
306 {
307 M4OSA_UInt32 code, l0 = 0, l1;
308 /* Reading 32 Bits from local cache buffer of Bitstream structure*/
309 code = p_bs->ui32TempBuff;
310
311 /* Checking in first 3 bits*/
312 if( code >> 29 )
313 {
314 l0 = Tab_MCS[(code >> 29)];
315 code = code >> (32 - l0);
316 H264MCS_flushBits(p_bs, l0);
317 }
318 else
319 {
320 if( code )
321 {
322 code <<= 3;
323
324 for ( l0 = 3; code < 0x80000000; code <<= 1, l0++ );
325
326 if( l0 < 16 ) /*all useful bits are inside the 32 bits read */
327 {
328 code = code >> (31 - l0);
329 H264MCS_flushBits(p_bs, 2 * l0 + 1);
330 }
331 else
332 { /* Read the useful bits in 2 parts */
333 l1 = ( l0 << 1) - 31;
334 code >>= l0;
335 H264MCS_flushBits(p_bs, 32);
336 code = ( code << l1) | H264MCS_getBits(p_bs, l1);
337 }
338 }
339 else
340 {
341 H264MCS_flushBits(p_bs, 32);
342
343 if( H264MCS_getBits(p_bs, 1) )
344 {
345 /* if number of leading 0's is 32, the only code allowed is 1 followed
346 by 32 0's */
347
348 /*reading 32 more bits from bitstream buffer*/
349 code = H264MCS_getBits(p_bs, 32);
350
351 if( code == 0 )
352 {
353 return (code - 1);
354 }
355 }
356 /*if number of leading 0's is >32, then symbol is >32 bits,
357 which is an error */
358 //p_bs->state = _BS_ERR;
359 //p_bs->flags |= _BF_SYM_ERR;
360 return (0);
361 }
362 }
363
364 if( 1 ) //(p_bs->state == _BS_OK)
365 {
366 return (code - 1);
367 }
368 else
369 {
370 return (0);
371 }
372 }
373
H264MCS_DecVLCReadSignedExpGolombCode(ComBitStreamMCS_t * p_bs)374 M4OSA_Int32 H264MCS_DecVLCReadSignedExpGolombCode( ComBitStreamMCS_t *p_bs )
375 {
376 M4OSA_Int32 codeNo, ret;
377
378 /* read the unsigned code number */
379 codeNo = H264MCS_DecVLCReadExpGolombCode(p_bs);
380
381 /* map to the signed value, if value is odd then it's positive,
382 if even then it's negative, formula is (-1)^(k+1)*CEIL(k/2) */
383
384 ret = (codeNo & 0x01) ? (( codeNo + 1) >> 1) : (( -codeNo) >> 1);
385
386 return ret;
387 }
388
DecBitStreamReset_MCS(ComBitStreamMCS_t * p_bs,M4OSA_UInt32 bytes_read)389 M4OSA_Void DecBitStreamReset_MCS( ComBitStreamMCS_t *p_bs,
390 M4OSA_UInt32 bytes_read )
391 {
392 p_bs->bitPos = 0;
393
394 p_bs->lastTotalBits = 0;
395 p_bs->numBitsInBuffer = bytes_read << 3;
396 p_bs->readableBytesInBuffer = bytes_read;
397 //p_bs->state = M4NO_ERROR;//_BS_OK;
398 //p_bs->flags = 0;
399
400 p_bs->ui32TempBuff = 0;
401 p_bs->i8BitCnt = 0;
402 p_bs->pui8BfrPtr = (M4OSA_Int8 *)p_bs->Buffer;
403 p_bs->ui32LastTwoBytes = 0xFFFFFFFF;
404 H264MCS_getBits(p_bs, 0);
405 }
406
NSWAVCMCS_initBitstream(NSWAVC_bitStream_t_MCS * bS)407 M4OSA_ERR NSWAVCMCS_initBitstream( NSWAVC_bitStream_t_MCS *bS )
408 {
409 bS->bitPos = 0;
410 bS->byteCnt = 0;
411 bS->currBuff = 0;
412 bS->prevByte = 0xff;
413 bS->prevPrevByte = 0xff;
414
415 return M4NO_ERROR;
416 }
417
NSWAVCMCS_putBits(NSWAVC_bitStream_t_MCS * bS,M4OSA_UInt32 value,M4OSA_UInt8 length)418 M4OSA_ERR NSWAVCMCS_putBits( NSWAVC_bitStream_t_MCS *bS, M4OSA_UInt32 value,
419 M4OSA_UInt8 length )
420 {
421 M4OSA_UInt32 maskedValue = 0, temp = 0;
422 M4OSA_UInt8 byteOne;
423
424 M4OSA_UInt32 len1 = (length == 32) ? 31 : length;
425
426 if( !(length) )
427 {
428 /* Length = 0, return OK*/
429 return M4NO_ERROR;
430 }
431
432 maskedValue = (M4OSA_UInt32)(value &(( 1 << len1) - 1));
433
434 if( 32 > (length + bS->bitPos) )
435 {
436 bS->bitPos += length;
437 bS->currBuff |= maskedValue << (32 - bS->bitPos);
438 }
439 else
440 {
441 temp = (( bS->bitPos + length) - 32);
442
443 bS->currBuff |= (maskedValue >> (temp));
444
445 byteOne =
446 bS->streamBuffer[bS->byteCnt++] = (M4OSA_UInt8)(bS->currBuff >> 24);
447
448 if( (( bS->prevPrevByte
449 == 0) & (bS->prevByte == 0) & (!(byteOne & 0xFC))) )
450 {
451 bS->byteCnt -= 1;
452 bS->prevPrevByte = bS->streamBuffer[bS->byteCnt++] = 0x03;
453 bS->prevByte = bS->streamBuffer[bS->byteCnt++] = byteOne;
454 }
455 else
456 {
457 bS->prevPrevByte = bS->prevByte;
458 bS->prevByte = byteOne;
459 }
460 byteOne = bS->streamBuffer[bS->byteCnt++] =
461 (M4OSA_UInt8)(( bS->currBuff >> 16) & 0xff);
462
463 if( (( bS->prevPrevByte
464 == 0) & (bS->prevByte == 0) & (!(byteOne & 0xFC))) )
465 {
466 bS->byteCnt -= 1;
467 bS->prevPrevByte = bS->streamBuffer[bS->byteCnt++] = 0x03;
468 bS->prevByte = bS->streamBuffer[bS->byteCnt++] = byteOne;
469 }
470 else
471 {
472 bS->prevPrevByte = bS->prevByte;
473 bS->prevByte = byteOne;
474 }
475 byteOne = bS->streamBuffer[bS->byteCnt++] =
476 (M4OSA_UInt8)(( bS->currBuff >> 8) & 0xff);
477
478 if( (( bS->prevPrevByte
479 == 0) & (bS->prevByte == 0) & (!(byteOne & 0xFC))) )
480 {
481 bS->byteCnt -= 1;
482 bS->prevPrevByte = bS->streamBuffer[bS->byteCnt++] = 0x03;
483 bS->prevByte = bS->streamBuffer[bS->byteCnt++] = byteOne;
484 }
485 else
486 {
487 bS->prevPrevByte = bS->prevByte;
488 bS->prevByte = byteOne;
489 }
490 byteOne = bS->streamBuffer[bS->byteCnt++] =
491 (M4OSA_UInt8)((bS->currBuff) &0xff);
492
493 if( (( bS->prevPrevByte
494 == 0) & (bS->prevByte == 0) & (!(byteOne & 0xFC))) )
495 {
496 bS->byteCnt -= 1;
497 bS->prevPrevByte = bS->streamBuffer[bS->byteCnt++] = 0x03;
498 bS->prevByte = bS->streamBuffer[bS->byteCnt++] = byteOne;
499 }
500 else
501 {
502 bS->prevPrevByte = bS->prevByte;
503 bS->prevByte = byteOne;
504 }
505
506 bS->currBuff = 0;
507
508 bS->currBuff |= ( maskedValue &(( 1 << temp) - 1)) << (32 - temp);
509
510 bS->bitPos = temp;
511 }
512
513 return M4NO_ERROR;
514 }
515
NSWAVCMCS_putBit(NSWAVC_bitStream_t_MCS * bS,M4OSA_UInt32 value)516 M4OSA_ERR NSWAVCMCS_putBit( NSWAVC_bitStream_t_MCS *bS, M4OSA_UInt32 value )
517 {
518 M4OSA_UInt32 maskedValue = 0, temp = 0;
519 M4OSA_UInt8 byteOne;
520
521 maskedValue = (value ? 1 : 0);
522
523 if( 32 > (1 + bS->bitPos) )
524 {
525 bS->bitPos += 1;
526 bS->currBuff |= maskedValue << (32 - bS->bitPos);
527 }
528 else
529 {
530 temp = 0;
531
532 bS->currBuff |= (maskedValue);
533
534 /* writing it to memory*/
535 byteOne =
536 bS->streamBuffer[bS->byteCnt++] =
537 (M4OSA_UInt8)(bS->currBuff >> 24);
538
539 if( (( bS->prevPrevByte
540 == 0) & (bS->prevByte == 0) & (!(byteOne & 0xFC))) )
541 {
542 bS->byteCnt -= 1;
543 bS->prevPrevByte = bS->streamBuffer[bS->byteCnt++] = 0x03;
544 bS->prevByte = bS->streamBuffer[bS->byteCnt++] = byteOne;
545 }
546 else
547 {
548 bS->prevPrevByte = bS->prevByte;
549 bS->prevByte = byteOne;
550 }
551 byteOne = bS->streamBuffer[bS->byteCnt++] =
552 (M4OSA_UInt8)(( bS->currBuff >> 16) & 0xff);
553
554 if( (( bS->prevPrevByte
555 == 0) & (bS->prevByte == 0) & (!(byteOne & 0xFC))) )
556 {
557 bS->byteCnt -= 1;
558 bS->prevPrevByte = bS->streamBuffer[bS->byteCnt++] = 0x03;
559 bS->prevByte = bS->streamBuffer[bS->byteCnt++] = byteOne;
560 }
561 else
562 {
563 bS->prevPrevByte = bS->prevByte;
564 bS->prevByte = byteOne;
565 }
566 byteOne = bS->streamBuffer[bS->byteCnt++] =
567 (M4OSA_UInt8)(( bS->currBuff >> 8) & 0xff);
568
569 if( (( bS->prevPrevByte
570 == 0) & (bS->prevByte == 0) & (!(byteOne & 0xFC))) )
571 {
572 bS->byteCnt -= 1;
573 bS->prevPrevByte = bS->streamBuffer[bS->byteCnt++] = 0x03;
574 bS->prevByte = bS->streamBuffer[bS->byteCnt++] = byteOne;
575 }
576 else
577 {
578 bS->prevPrevByte = bS->prevByte;
579 bS->prevByte = byteOne;
580 }
581 byteOne = bS->streamBuffer[bS->byteCnt++] =
582 (M4OSA_UInt8)((bS->currBuff) &0xff);
583
584 if( (( bS->prevPrevByte
585 == 0) & (bS->prevByte == 0) & (!(byteOne & 0xFC))) )
586 {
587 bS->byteCnt -= 1;
588 bS->prevPrevByte = bS->streamBuffer[bS->byteCnt++] = 0x03;
589 bS->prevByte = bS->streamBuffer[bS->byteCnt++] = byteOne;
590 }
591 else
592 {
593 bS->prevPrevByte = bS->prevByte;
594 bS->prevByte = byteOne;
595 }
596 bS->currBuff = 0;
597 bS->bitPos = 0;
598 }
599
600 return M4NO_ERROR;
601 }
602
NSWAVCMCS_putRbspTbits(NSWAVC_bitStream_t_MCS * bS)603 M4OSA_Int32 NSWAVCMCS_putRbspTbits( NSWAVC_bitStream_t_MCS *bS )
604 {
605 M4OSA_UInt8 trailBits = 0;
606 M4OSA_UInt8 byteCnt = 0;
607
608 trailBits = (M4OSA_UInt8)(bS->bitPos % 8);
609
610 /* Already in the byte aligned position,
611 RBSP trailing bits will be 1000 0000 */
612 if( 0 == trailBits )
613 {
614 trailBits = (1 << 7);
615 NSWAVCMCS_putBits(bS, trailBits, 8);
616 }
617 else
618 {
619 trailBits = (8 - trailBits);
620 NSWAVCMCS_putBit(bS, 1);
621 trailBits--;
622
623 if( trailBits )
624 { /* put trailBits times zeros */
625 NSWAVCMCS_putBits(bS, 0, trailBits);
626 }
627 }
628
629 /* For writting the currBuff in streamBuff 4byte alignment is required*/
630 byteCnt = (M4OSA_UInt8)(( bS->bitPos + 4) / 8);
631
632 switch( byteCnt )
633 {
634 case 1:
635 bS->streamBuffer[bS->byteCnt++] = (M4OSA_UInt8)(bS->currBuff >> 24);
636 break;
637
638 case 2:
639 bS->streamBuffer[bS->byteCnt++] = (M4OSA_UInt8)(bS->currBuff >> 24);
640 bS->streamBuffer[bS->byteCnt++] =
641 (M4OSA_UInt8)(( bS->currBuff >> 16) & 0xff);
642 break;
643
644 case 3:
645 bS->streamBuffer[bS->byteCnt++] = (M4OSA_UInt8)(bS->currBuff >> 24);
646 bS->streamBuffer[bS->byteCnt++] =
647 (M4OSA_UInt8)(( bS->currBuff >> 16) & 0xff);
648 bS->streamBuffer[bS->byteCnt++] =
649 (M4OSA_UInt8)(( bS->currBuff >> 8) & 0xff);
650
651 break;
652
653 default:
654 /* It will not come here */
655 break;
656 }
657
658 // bS->bitPos =0;
659 // bS->currBuff = 0;
660
661 return M4NO_ERROR;
662 }
663
NSWAVCMCS_uExpVLC(NSWAVC_bitStream_t_MCS * bS,M4OSA_Int32 codeNum)664 M4OSA_ERR NSWAVCMCS_uExpVLC( NSWAVC_bitStream_t_MCS *bS, M4OSA_Int32 codeNum )
665 {
666
667 M4OSA_Int32 loop, temp;
668 M4OSA_Int32 data = 0;
669 M4OSA_UInt8 codeLen = 0;
670
671 /* The codeNum cannot be less than zero for this ue(v) */
672 if( codeNum < 0 )
673 {
674 return 0;
675 }
676
677 /* Implementation for Encoding of the Table 9-1 in the Standard */
678 temp = codeNum + 1;
679
680 for ( loop = 0; temp != 0; loop++ )
681 {
682 temp /= 2;
683 }
684
685 codeLen = (( loop * 2) - 1);
686
687 data = codeNum + 1;
688
689 NSWAVCMCS_putBits(bS, data, codeLen);
690
691 return M4NO_ERROR;
692 }
693
NSWAVCMCS_sExpVLC(NSWAVC_bitStream_t_MCS * bS,M4OSA_Int32 codeNum)694 M4OSA_ERR NSWAVCMCS_sExpVLC( NSWAVC_bitStream_t_MCS *bS, M4OSA_Int32 codeNum )
695 {
696
697 M4OSA_Int32 loop, temp1, temp2;
698 M4OSA_Int32 data = 0;
699 M4OSA_UInt8 codeLen = 0, isPositive = 0;
700 M4OSA_UInt32 abscodeNum;
701
702 if( codeNum > 0 )
703 {
704 isPositive = 1;
705 }
706
707 if( codeNum > 0 )
708 {
709 abscodeNum = codeNum;
710 }
711 else
712 {
713 abscodeNum = -codeNum;
714 }
715
716 temp1 = ( ( ( abscodeNum) << 1) - isPositive) + 1;
717 temp2 = temp1;
718
719 for ( loop = 0; loop < 16 && temp2 != 0; loop++ )
720 {
721 temp2 /= 2;
722 }
723
724 codeLen = ( loop * 2) - 1;
725
726 data = temp1;
727
728 NSWAVCMCS_putBits(bS, data, codeLen);
729
730 return M4NO_ERROR;
731 }
732
H264MCS_ProcessEncodedNALU(M4OSA_Void * ainstance,M4OSA_UInt8 * inbuff,M4OSA_Int32 inbuf_size,M4OSA_UInt8 * outbuff,M4OSA_Int32 * outbuf_size)733 M4OSA_ERR H264MCS_ProcessEncodedNALU( M4OSA_Void *ainstance,
734 M4OSA_UInt8 *inbuff,
735 M4OSA_Int32 inbuf_size,
736 M4OSA_UInt8 *outbuff,
737 M4OSA_Int32 *outbuf_size )
738 {
739 ComBitStreamMCS_t *p_bs, bs;
740 NSWAVC_MCS_t *instance;
741 M4OSA_UInt8 nalu_info;
742 M4OSA_Int32 forbidden_bit, nal_ref_idc, nal_unit_type;
743 M4OSA_Int32 first_mb_in_slice, slice_type, pic_parameter_set_id, frame_num;
744 M4OSA_Int32 seq_parameter_set_id;
745 M4OSA_UInt8 temp1, temp2, temp3, temp4;
746 M4OSA_Int32 temp_frame_num;
747 M4OSA_Int32 bitstoDiacard, bytes;
748 M4OSA_UInt32 mask_bits = 0xFFFFFFFF;
749 M4OSA_Int32 new_bytes, init_bit_pos;
750 M4OSA_UInt32 nal_size;
751 M4OSA_UInt32 cnt;
752 M4OSA_UInt32 outbuffpos = 0;
753 M4OSA_UInt32 nal_size_low16, nal_size_high16;
754 M4OSA_UInt32 frame_size = 0;
755 M4OSA_UInt32 temp = 0;
756
757 // StageFright encoder does not provide the size in the first 4 bytes of the AU, add it
758 M4OSA_Int8 *pTmpBuff1 = M4OSA_NULL;
759 M4OSA_Int8 *pTmpBuff2 = M4OSA_NULL;
760
761 p_bs = &bs;
762 instance = (NSWAVC_MCS_t *)ainstance;
763
764 M4OSA_TRACE1_2(
765 "In H264MCS_ProcessEncodedNALU with FrameSize = %d inBuf_Size=%d",
766 frame_size, inbuf_size);
767
768 // StageFright codecs may add a start code, make sure it is not present
769
770 if( !memcmp((void *)inbuff,
771 "\x00\x00\x00\x01", 4) )
772 {
773 M4OSA_TRACE1_3(
774 "H264MCS_ProcessNALU ERROR : NALU start code has not been removed %d "
775 "0x%X 0x%X", inbuf_size, ((M4OSA_UInt32 *)inbuff)[0],
776 ((M4OSA_UInt32 *)inbuff)[1]);
777
778 return M4ERR_PARAMETER;
779 }
780
781 // StageFright encoder does not provide the size in the first 4 bytes of the AU, add it
782 pTmpBuff1 = (M4OSA_Int8 *)M4OSA_32bitAlignedMalloc(inbuf_size + 4, M4MCS,
783 (M4OSA_Char *)"tmpNALU");
784 memcpy((void *)(pTmpBuff1 + 4), (void *)inbuff,
785 inbuf_size);
786 pTmpBuff1[3] = ( (M4OSA_UInt32)inbuf_size) & 0x000000FF;
787 pTmpBuff1[2] = ( (M4OSA_UInt32)inbuf_size >> 8) & 0x000000FF;
788 pTmpBuff1[1] = ( (M4OSA_UInt32)inbuf_size >> 16) & 0x000000FF;
789 pTmpBuff1[0] = ( (M4OSA_UInt32)inbuf_size >> 24) & 0x000000FF;
790 pTmpBuff2 = (M4OSA_Int8 *)inbuff;
791 inbuff = (M4OSA_UInt8 *)pTmpBuff1;
792 inbuf_size += 4;
793
794 // Make sure the available size was set
795 if( inbuf_size >= *outbuf_size )
796 {
797 M4OSA_TRACE1_1(
798 "!!! H264MCS_ProcessNALU ERROR : specified available size is incorrect %d ",
799 *outbuf_size);
800 return M4ERR_PARAMETER;
801 }
802
803
804
805 while( (M4OSA_Int32)frame_size < inbuf_size )
806 {
807 mask_bits = 0xFFFFFFFF;
808 p_bs->Buffer = (M4OSA_UInt8 *)(inbuff + frame_size);
809
810 // Use unsigned value to fix errors due to bit sign extension, this fix should be generic
811
812 nal_size_high16 = ( ( (M4OSA_UInt8 *)p_bs->Buffer)[0] << 8)
813 + ((M4OSA_UInt8 *)p_bs->Buffer)[1];
814 nal_size_low16 = ( ( (M4OSA_UInt8 *)p_bs->Buffer)[2] << 8)
815 + ((M4OSA_UInt8 *)p_bs->Buffer)[3];
816
817 nalu_info = (unsigned char)p_bs->Buffer[4];
818
819 outbuff[outbuffpos] = p_bs->Buffer[4];
820
821 p_bs->Buffer = p_bs->Buffer + 5;
822
823 p_bs->bitPos = 0;
824 p_bs->lastTotalBits = 0;
825 p_bs->numBitsInBuffer = ( inbuf_size - frame_size - 5) << 3;
826 p_bs->readableBytesInBuffer = inbuf_size - frame_size - 5;
827
828 p_bs->ui32TempBuff = 0;
829 p_bs->i8BitCnt = 0;
830 p_bs->pui8BfrPtr = (M4OSA_Int8 *)p_bs->Buffer;
831 p_bs->ui32LastTwoBytes = 0xFFFFFFFF;
832
833 H264MCS_getBits(p_bs, 0);
834
835 nal_size = ( nal_size_high16 << 16) + nal_size_low16;
836
837 frame_size += nal_size + 4;
838
839 forbidden_bit = ( nalu_info >> 7) & 1;
840 nal_ref_idc = ( nalu_info >> 5) & 3;
841 nal_unit_type = (nalu_info) &0x1f;
842
843 NSWAVCMCS_initBitstream(&instance->encbs);
844
845 instance->encbs.streamBuffer = outbuff + outbuffpos + 1;
846
847 if( nal_unit_type == 8 )
848 {
849 M4OSA_TRACE1_0("Error : PPS");
850 return 0;
851 }
852
853 if( nal_unit_type == 7 )
854 {
855 /*SPS Packet */
856 M4OSA_TRACE1_0("Error : SPS");
857 return 0;
858 }
859
860 if( (nal_unit_type == 5) )
861 {
862 instance->frame_count = 0;
863 instance->POC_lsb = 0;
864 }
865
866 if( ( nal_unit_type == 1) || (nal_unit_type == 5) )
867 {
868 first_mb_in_slice = H264MCS_DecVLCReadExpGolombCode(p_bs);
869 slice_type = H264MCS_DecVLCReadExpGolombCode(p_bs);
870 pic_parameter_set_id = H264MCS_DecVLCReadExpGolombCode(p_bs);
871
872 /* First MB in slice */
873 NSWAVCMCS_uExpVLC(&instance->encbs, first_mb_in_slice);
874
875 /* Slice Type */
876 NSWAVCMCS_uExpVLC(&instance->encbs, slice_type);
877
878 /* Picture Parameter set Id */
879 pic_parameter_set_id = instance->encoder_pps.pic_parameter_set_id;
880 NSWAVCMCS_uExpVLC(&instance->encbs, pic_parameter_set_id);
881
882 temp = H264MCS_getBits(p_bs,
883 instance->encoder_sps.log2_max_frame_num_minus4 + 4);
884 NSWAVCMCS_putBits(&instance->encbs, instance->frame_count,
885 instance->clip_sps.log2_max_frame_num_minus4 + 4);
886
887 // In Baseline Profile: frame_mbs_only_flag should be ON
888 if( nal_unit_type == 5 )
889 {
890 temp = H264MCS_DecVLCReadExpGolombCode(p_bs);
891 NSWAVCMCS_uExpVLC(&instance->encbs, temp);
892 }
893
894 if( instance->encoder_sps.pic_order_cnt_type == 0 )
895 {
896 temp = H264MCS_getBits(p_bs,
897 instance->encoder_sps.log2_max_pic_order_cnt_lsb_minus4
898 + 4);
899
900 // in baseline profile field_pic_flag should be off.
901 if( instance->encoder_pps.pic_order_present_flag )
902 {
903 temp = H264MCS_DecVLCReadSignedExpGolombCode(p_bs);
904 }
905 }
906
907 if( ( instance->encoder_sps.pic_order_cnt_type == 1)
908 && (instance->encoder_sps.delta_pic_order_always_zero_flag) )
909 {
910 temp = H264MCS_DecVLCReadSignedExpGolombCode(p_bs);
911
912 // in baseline profile field_pic_flag should be off.
913 if( instance->encoder_pps.pic_order_present_flag )
914 {
915 temp = H264MCS_DecVLCReadSignedExpGolombCode(p_bs);
916 }
917 }
918
919 if( instance->clip_sps.pic_order_cnt_type == 0 )
920 {
921 NSWAVCMCS_putBits(&instance->encbs, instance->POC_lsb,
922 instance->clip_sps.log2_max_pic_order_cnt_lsb_minus4 + 4);
923
924 // in baseline profile field_pic_flag should be off.
925 if( instance->encoder_pps.pic_order_present_flag )
926 {
927 NSWAVCMCS_sExpVLC(&instance->encbs, 0);
928 }
929 }
930
931 if( ( instance->clip_sps.pic_order_cnt_type == 1)
932 && (instance->clip_sps.delta_pic_order_always_zero_flag) )
933 {
934 NSWAVCMCS_sExpVLC(&instance->encbs, 0);
935
936 // in baseline profile field_pic_flag should be off.
937 if( instance->encoder_pps.pic_order_present_flag )
938 {
939 NSWAVCMCS_sExpVLC(&instance->encbs, 0);
940 }
941 }
942
943 cnt = p_bs->bitPos & 0x7;
944
945 if( cnt )
946 {
947 cnt = 8 - cnt;
948 temp = H264MCS_getBits(p_bs, cnt);
949 NSWAVCMCS_putBits(&instance->encbs, temp, cnt);
950 }
951
952 cnt = p_bs->bitPos >> 3;
953
954 while( cnt < (nal_size - 2) )
955 {
956 temp = H264MCS_getBits(p_bs, 8);
957 NSWAVCMCS_putBits(&instance->encbs, temp, 8);
958 cnt = p_bs->bitPos >> 3;
959 }
960
961 temp = H264MCS_getBits(p_bs, 8);
962
963 if( temp != 0 )
964 {
965 cnt = 0;
966
967 while( ( temp & 0x1) == 0 )
968 {
969 cnt++;
970 temp = temp >> 1;
971 }
972 cnt++;
973 temp = temp >> 1;
974
975 if( 8 - cnt )
976 {
977 NSWAVCMCS_putBits(&instance->encbs, temp, (8 - cnt));
978 }
979
980 NSWAVCMCS_putRbspTbits(&instance->encbs);
981 }
982 else
983 {
984
985 M4OSA_TRACE1_1(
986 "H264MCS_ProcessEncodedNALU : 13 temp = 0 trailing bits = %d",
987 instance->encbs.bitPos % 8);
988
989 if( instance->encbs.bitPos % 8 )
990 {
991 NSWAVCMCS_putBits(&instance->encbs, 0,
992 (8 - instance->encbs.bitPos % 8));
993 }
994 }
995
996 temp = instance->encbs.byteCnt;
997 temp = temp + 1;
998
999 outbuffpos = outbuffpos + temp;
1000 }
1001 }
1002
1003 *outbuf_size = outbuffpos;
1004
1005 instance->POC_lsb = instance->POC_lsb + 1;
1006
1007 if( instance->POC_lsb == instance->POC_lsb_mod )
1008 {
1009 instance->POC_lsb = 0;
1010 }
1011 instance->frame_count = instance->frame_count + 1;
1012
1013 if( instance->frame_count == instance->frame_mod_count )
1014 {
1015 instance->frame_count = 0;
1016 }
1017
1018 // StageFright encoder does not provide the size in the first 4 bytes of the AU, add it
1019
1020 free(pTmpBuff1);
1021 pTmpBuff1 = M4OSA_NULL;
1022 inbuff = (M4OSA_UInt8 *)pTmpBuff2;
1023
1024 return M4NO_ERROR;
1025 }
1026
DecSPSMCS(ComBitStreamMCS_t * p_bs,ComSequenceParameterSet_t_MCS * sps)1027 M4OSA_Int32 DecSPSMCS( ComBitStreamMCS_t *p_bs,
1028 ComSequenceParameterSet_t_MCS *sps )
1029 {
1030 M4OSA_UInt32 i;
1031 M4OSA_Int32 temp_max_dpb_size;
1032 M4OSA_Int32 nb_ignore_bits;
1033 M4OSA_Int32 error;
1034 M4OSA_UInt8 profile_idc, level_idc, reserved_zero_4bits,
1035 seq_parameter_set_id;
1036 M4OSA_UInt8 constraint_set0_flag, constraint_set1_flag,
1037 constraint_set2_flag, constraint_set3_flag;
1038
1039 sps->profile_idc = (M4OSA_UInt8)H264MCS_getBits(p_bs, 8);
1040 sps->constraint_set0_flag = (M4OSA_Bool)H264MCS_getBits(p_bs, 1);
1041 sps->constraint_set1_flag = (M4OSA_Bool)H264MCS_getBits(p_bs, 1);
1042 sps->constraint_set2_flag = (M4OSA_Bool)H264MCS_getBits(p_bs, 1);
1043 sps->constraint_set3_flag = (M4OSA_Bool)H264MCS_getBits(p_bs, 1);
1044 reserved_zero_4bits = (M4OSA_UInt8)H264MCS_getBits(p_bs, 4);
1045 sps->level_idc = (M4OSA_UInt8)H264MCS_getBits(p_bs, 8);
1046 sps->seq_parameter_set_id =
1047 (M4OSA_UInt8)H264MCS_DecVLCReadExpGolombCode(p_bs);
1048 sps->log2_max_frame_num_minus4 =
1049 (M4OSA_UInt8)H264MCS_DecVLCReadExpGolombCode(p_bs);
1050 sps->MaxFrameNum = 1 << (sps->log2_max_frame_num_minus4 + 4);
1051 sps->pic_order_cnt_type =
1052 (M4OSA_UInt8)H264MCS_DecVLCReadExpGolombCode(p_bs);
1053
1054 if (sps->pic_order_cnt_type == 0)
1055 {
1056 sps->log2_max_pic_order_cnt_lsb_minus4 =
1057 (M4OSA_UInt8)H264MCS_DecVLCReadExpGolombCode(p_bs);
1058 sps->MaxPicOrderCntLsb =
1059 1 << (sps->log2_max_pic_order_cnt_lsb_minus4 + 4);
1060 }
1061 else if( sps->pic_order_cnt_type == 1 )
1062 {
1063 sps->delta_pic_order_always_zero_flag =
1064 (M4OSA_Bool)H264MCS_getBits(p_bs, 1);
1065
1066 // This fix should be generic to remove codec dependency
1067
1068 sps->offset_for_non_ref_pic =
1069 H264MCS_DecVLCReadSignedExpGolombCode(p_bs);
1070 sps->offset_for_top_to_bottom_field =
1071 H264MCS_DecVLCReadSignedExpGolombCode(p_bs);
1072
1073
1074 /*num_ref_frames_in_pic_order_cnt_cycle must be in the range 0, 255*/
1075
1076 sps->num_ref_frames_in_pic_order_cnt_cycle =
1077 (M4OSA_UInt8)H264MCS_DecVLCReadExpGolombCode(p_bs);
1078
1079 /* compute deltaPOC */
1080 sps->expectedDeltaPerPicOrderCntCycle = 0;
1081
1082 for ( i = 0; i < sps->num_ref_frames_in_pic_order_cnt_cycle; i++ )
1083 {
1084 // This fix should be generic to remove codec dependency
1085 sps->offset_for_ref_frame[i] =
1086 H264MCS_DecVLCReadSignedExpGolombCode(p_bs);
1087
1088 sps->expectedDeltaPerPicOrderCntCycle +=
1089 sps->offset_for_ref_frame[i];
1090 }
1091 }
1092
1093 /* num_ref_frames must be in the range 0,16 */
1094 sps->num_ref_frames = (M4OSA_UInt8)H264MCS_DecVLCReadExpGolombCode(p_bs);
1095 sps->gaps_in_frame_num_value_allowed_flag =
1096 (M4OSA_Bool)H264MCS_getBits(p_bs, 1);
1097
1098 sps->pic_width_in_mbs_minus1 =
1099 (M4OSA_UInt16)H264MCS_DecVLCReadExpGolombCode(p_bs);
1100 sps->pic_height_in_map_units_minus1 =
1101 (M4OSA_UInt16)H264MCS_DecVLCReadExpGolombCode(p_bs);
1102
1103 sps->frame_mbs_only_flag = (M4OSA_Bool)H264MCS_getBits(p_bs, 1);
1104
1105 if (!sps->frame_mbs_only_flag)
1106 {
1107 sps->mb_adaptive_frame_field_flag =
1108 (M4OSA_Bool)H264MCS_getBits(p_bs, 1);
1109 }
1110 else
1111 {
1112 sps->mb_adaptive_frame_field_flag = 0;
1113 }
1114
1115 sps->PicWidthInMbs = sps->pic_width_in_mbs_minus1 + 1;
1116 sps->FrameHeightInMbs = ( 2 - sps->frame_mbs_only_flag) * \
1117 (sps->pic_height_in_map_units_minus1 + 1);
1118 #ifdef _CAP_FMO_
1119
1120 sps->NumSliceGroupMapUnits =
1121 sps->PicWidthInMbs * (sps->pic_height_in_map_units_minus1 + 1);
1122 sps->MaxPicSizeInMbs = sps->PicWidthInMbs * sps->FrameHeightInMbs;
1123
1124 #endif /*_CAP_FMO_*/
1125
1126 sps->direct_8x8_inference_flag = (M4OSA_Bool)H264MCS_getBits(p_bs, 1);
1127
1128 if( sps->frame_mbs_only_flag == 0 )
1129 sps->direct_8x8_inference_flag = 1;
1130
1131 sps->frame_cropping_flag = (M4OSA_Bool)H264MCS_getBits(p_bs, 1);
1132
1133 if( sps->frame_cropping_flag )
1134 {
1135 sps->frame_crop_left_offset = H264MCS_DecVLCReadExpGolombCode(p_bs);
1136 sps->frame_crop_right_offset = H264MCS_DecVLCReadExpGolombCode(p_bs);
1137 sps->frame_crop_top_offset = H264MCS_DecVLCReadExpGolombCode(p_bs);
1138 sps->frame_crop_bottom_offset = H264MCS_DecVLCReadExpGolombCode(p_bs);
1139 }
1140 else
1141 {
1142 sps->frame_crop_left_offset = 0;
1143 sps->frame_crop_right_offset = 0;
1144 sps->frame_crop_top_offset = 0;
1145 sps->frame_crop_bottom_offset = 0;
1146 }
1147
1148 sps->vui_parameters_present_flag = (M4OSA_Bool)H264MCS_getBits(p_bs, 1);
1149
1150 if (sps->vui_parameters_present_flag) {
1151 /* no error message as stream can be decoded without VUI messages */
1152 }
1153
1154 return M4NO_ERROR;
1155 }
1156
DecPPSMCS(ComBitStreamMCS_t * p_bs,ComPictureParameterSet_t_MCS * pps)1157 M4OSA_Int32 DecPPSMCS( ComBitStreamMCS_t *p_bs,
1158 ComPictureParameterSet_t_MCS *pps )
1159 {
1160 M4OSA_Int32 error;
1161 M4OSA_UInt32 pic_parameter_set_id;
1162
1163 #ifdef _CAP_FMO_
1164 M4OSA_UInt32 i, length, v;
1165 #endif
1166
1167 M4OSA_Int32 nb_ignore_bits;
1168
1169 pic_parameter_set_id = H264MCS_DecVLCReadExpGolombCode(p_bs);
1170 pps->pic_parameter_set_id = (M4OSA_UInt8)pic_parameter_set_id;
1171
1172 pps->seq_parameter_set_id =
1173 (M4OSA_UInt8)H264MCS_DecVLCReadExpGolombCode(p_bs);
1174
1175 /* entropy_coding_mode_flag must be 0 or 1 */
1176 pps->entropy_coding_mode_flag = (M4OSA_Bool)H264MCS_getBits(p_bs, 1);
1177 pps->pic_order_present_flag = (M4OSA_Bool)H264MCS_getBits(p_bs, 1);
1178
1179 pps->num_slice_groups_minus1 =
1180 (M4OSA_UInt8)H264MCS_DecVLCReadExpGolombCode(p_bs);
1181
1182 #ifdef _CAP_FMO_
1183 /* FMO stuff begins here */
1184
1185 pps->map_initialized = FALSE;
1186
1187 if( pps->num_slice_groups_minus1 > 0 )
1188 {
1189 pps->slice_group_map_type =
1190 (M4OSA_UInt8)H264MCS_DecVLCReadExpGolombCode(p_bs);
1191
1192 switch( pps->slice_group_map_type )
1193 {
1194 case 0:
1195 for ( i = 0; i <= pps->num_slice_groups_minus1; i++ )
1196 {
1197 pps->run_length_minus1[i] =
1198 (M4OSA_UInt16)H264MCS_DecVLCReadExpGolombCode(p_bs);
1199 }
1200 break;
1201
1202 case 2:
1203 for ( i = 0; i < pps->num_slice_groups_minus1; i++ )
1204 {
1205 pps->top_left[i] =
1206 (M4OSA_UInt16)H264MCS_DecVLCReadExpGolombCode(p_bs);
1207 pps->bottom_right[i] =
1208 (M4OSA_UInt16)H264MCS_DecVLCReadExpGolombCode(p_bs);
1209 }
1210 break;
1211
1212 case 3:
1213 case 4:
1214 case 5:
1215 pps->slice_group_change_direction_flag =
1216 (M4OSA_Bool)H264MCS_getBits(p_bs, 1);
1217 pps->slice_group_change_rate_minus1 =
1218 (M4OSA_UInt16)H264MCS_DecVLCReadExpGolombCode(p_bs);
1219 break;
1220
1221 case 6:
1222 pps->pic_size_in_map_units_minus1 =
1223 (M4OSA_UInt16)H264MCS_DecVLCReadExpGolombCode(p_bs);
1224
1225 pps->slice_group_id = (H264UInt8
1226 *)M4H264Dec_malloc((pps->pic_size_in_map_units_minus1
1227 + 1), M4H264_COREID, (M4OSA_Char *)"PPS");
1228
1229 if (M4OSA_NULL == pps->slice_group_id)
1230 {
1231 M4OSA_TRACE1_0("DecPPSMCS: allocation error");
1232 return M4ERR_ALLOC;
1233 }
1234
1235 for ( length = 0, v = pps->num_slice_groups_minus1 + 1; v != 0;
1236 v >>= 1, length++ );
1237
1238 for ( i = 0; i <= pps->pic_size_in_map_units_minus1; i++ )
1239 {
1240 pps->slice_group_id[i] =
1241 (M4OSA_UInt8)getBits(p_vlc_engine->p_bs, length);
1242 }
1243 break;
1244 }
1245 }
1246 else
1247 {
1248 pps->slice_group_map_type = 0;
1249 }
1250 /* End of FMO stuff */
1251
1252 #else
1253
1254 #endif /* _CAP_FMO_ */
1255
1256 /* num_ref_idx_l0_active_minus1 must be in the range 0, 31 */
1257
1258 pps->num_ref_idx_l0_active_minus1 =
1259 (M4OSA_UInt8)H264MCS_DecVLCReadExpGolombCode(p_bs);
1260 /* num_ref_idx_l1_active_minus1 must be in the range 0, 31 */
1261 pps->num_ref_idx_l1_active_minus1 =
1262 (M4OSA_UInt8)H264MCS_DecVLCReadExpGolombCode(p_bs);
1263 pps->weighted_pred_flag = (M4OSA_Bool)H264MCS_getBits(p_bs, 1);
1264
1265 /* weighted_bipred_idc must be in the range 0,2 */
1266 pps->weighted_bipred_idc = (M4OSA_Bool)H264MCS_getBits(p_bs, 2);
1267
1268 /* pic_init_qp_minus26 must be in the range -26,25 */
1269 pps->pic_init_qp_minus26 =
1270 (M4OSA_Int16)H264MCS_DecVLCReadSignedExpGolombCode(p_bs);
1271
1272 /* pic_init_qs_minus26 must be in the range -26,25 */
1273 pps->pic_init_qs_minus26 =
1274 (M4OSA_Int16)H264MCS_DecVLCReadSignedExpGolombCode(p_bs);
1275
1276 /* chroma_qp_index_offset must be in the range -12,+12 */
1277 pps->chroma_qp_index_offset =
1278 (M4OSA_Int16)H264MCS_DecVLCReadSignedExpGolombCode(p_bs);
1279 pps->deblocking_filter_control_present_flag =
1280 (M4OSA_Bool)H264MCS_getBits(p_bs, 1);
1281 pps->constrained_intra_pred_flag = (M4OSA_Bool)H264MCS_getBits(p_bs, 1);
1282 pps->redundant_pic_cnt_present_flag = (M4OSA_Bool)H264MCS_getBits(p_bs, 1);
1283
1284 return M4NO_ERROR;
1285 }
1286
H264MCS_ProcessSPS_PPS(NSWAVC_MCS_t * instance,M4OSA_UInt8 * inbuff,M4OSA_Int32 inbuf_size)1287 M4OSA_ERR H264MCS_ProcessSPS_PPS( NSWAVC_MCS_t *instance, M4OSA_UInt8 *inbuff,
1288 M4OSA_Int32 inbuf_size )
1289 {
1290 ComBitStreamMCS_t *p_bs, bs;
1291 ComBitStreamMCS_t *p_bs1, bs1;
1292
1293 M4OSA_UInt8 nalu_info = 0;
1294 M4OSA_Int32 forbidden_bit, nal_ref_idc, nal_unit_type;
1295 M4OSA_Int32 first_mb_in_slice, slice_type, pic_parameter_set_id = 0,
1296 frame_num;
1297 M4OSA_Int32 seq_parameter_set_id;
1298 M4OSA_UInt8 temp1, temp2, temp3, temp4;
1299 M4OSA_Int32 temp_frame_num;
1300 M4OSA_Int32 bitstoDiacard, bytes;
1301 M4OSA_UInt32 mask_bits = 0xFFFFFFFF;
1302 M4OSA_Int32 new_bytes, init_bit_pos;
1303 M4OSA_UInt32 nal_size = 0;
1304 M4OSA_UInt32 cnt, cnt1;
1305 M4OSA_UInt32 outbuffpos = 0;
1306 M4OSA_UInt32 nal_size_low16, nal_size_high16;
1307 M4OSA_UInt32 frame_size = 0;
1308 M4OSA_UInt32 temp = 0;
1309 M4OSA_UInt8 *lClipDSI;
1310 M4OSA_UInt8 *lClipDSI_PPS_start;
1311 M4OSA_UInt32 lClipDSI_PPS_offset = 0;
1312
1313 M4OSA_UInt8 *lPPS_Buffer = M4OSA_NULL;
1314 M4OSA_UInt32 lPPS_Buffer_Size = 0;
1315
1316 M4OSA_UInt32 lSize, lSize1;
1317 M4OSA_UInt32 lActiveSPSID_Clip;
1318 M4OSA_UInt32 lClipPPSRemBits = 0;
1319
1320 M4OSA_UInt32 lEncoder_SPSID = 0;
1321 M4OSA_UInt32 lEncoder_PPSID = 0;
1322 M4OSA_UInt32 lEncoderPPSRemBits = 0;
1323 M4OSA_UInt32 lFound = 0;
1324 M4OSA_UInt32 size;
1325
1326 M4OSA_UInt8 Clip_SPSID[32] = { 0 };
1327 M4OSA_UInt8 Clip_UsedSPSID[32] = { 0 };
1328 M4OSA_UInt8 Clip_PPSID[256] = { 0 };
1329 M4OSA_UInt8 Clip_SPSID_in_PPS[256] = { 0 };
1330 M4OSA_UInt8 Clip_UsedPPSID[256] = { 0 };
1331 M4OSA_ERR err = M4NO_ERROR;
1332
1333 p_bs = &bs;
1334 p_bs1 = &bs1;
1335
1336 /* Find the active SPS ID */
1337 M4OSA_DEBUG_IF2((M4OSA_NULL == instance), M4ERR_PARAMETER,
1338 "H264MCS_ProcessSPS_PPS: instance is M4OSA_NULL");
1339
1340 switch( instance->m_pDecoderSpecificInfo[4] & 0x3 )
1341 {
1342 case 0:
1343 instance->m_Num_Bytes_NALUnitLength = 1;
1344 break;
1345
1346 case 1:
1347 instance->m_Num_Bytes_NALUnitLength = 2;
1348 break;
1349
1350 case 3:
1351 //Note: Current code supports only this...
1352 instance->m_Num_Bytes_NALUnitLength = 4;
1353 break;
1354 }
1355
1356 instance->m_encoder_SPS_Cnt = instance->m_pDecoderSpecificInfo[5] & 0x1F;
1357
1358 lClipDSI = instance->m_pDecoderSpecificInfo + 6;
1359
1360 lClipDSI_PPS_offset = 6;
1361
1362 for ( cnt = 0; cnt < instance->m_encoder_SPS_Cnt; cnt++ )
1363 {
1364 lSize = ( lClipDSI[0] << 8) + lClipDSI[1];
1365 lClipDSI = lClipDSI + 2;
1366
1367 p_bs->Buffer = (M4OSA_UInt8 *)(lClipDSI + 4);
1368 DecBitStreamReset_MCS(p_bs, lSize - 4);
1369
1370 Clip_SPSID[cnt] = H264MCS_DecVLCReadExpGolombCode(p_bs);
1371 Clip_UsedSPSID[Clip_SPSID[cnt]] = 1;
1372
1373 lClipDSI = lClipDSI + lSize;
1374 lClipDSI_PPS_offset = lClipDSI_PPS_offset + 2 + lSize;
1375 }
1376
1377 instance->m_encoder_PPS_Cnt = lClipDSI[0];
1378 lClipDSI = lClipDSI + 1;
1379
1380 lClipDSI_PPS_start = lClipDSI;
1381
1382 for ( cnt = 0; cnt < instance->m_encoder_PPS_Cnt; cnt++ )
1383 {
1384 lSize = ( lClipDSI[0] << 8) + lClipDSI[1];
1385 lClipDSI = lClipDSI + 2;
1386
1387 p_bs->Buffer = (M4OSA_UInt8 *)(lClipDSI + 1);
1388 DecBitStreamReset_MCS(p_bs, lSize - 1);
1389
1390 Clip_PPSID[cnt] = H264MCS_DecVLCReadExpGolombCode(p_bs);
1391 Clip_UsedPPSID[Clip_PPSID[cnt]] = 1;
1392 Clip_SPSID_in_PPS[Clip_PPSID[cnt]] =
1393 H264MCS_DecVLCReadExpGolombCode(p_bs);
1394
1395 lClipDSI = lClipDSI + lSize;
1396 }
1397
1398 /* Find the clip SPS ID used at the cut start frame */
1399 while( ( (M4OSA_Int32)frame_size) < inbuf_size )
1400 {
1401 mask_bits = 0xFFFFFFFF;
1402 p_bs->Buffer = (M4OSA_UInt8 *)(inbuff + frame_size);
1403
1404 switch( instance->m_Num_Bytes_NALUnitLength )
1405 {
1406 case 1:
1407 nal_size = (unsigned char)p_bs->Buffer[0];
1408 nalu_info = (unsigned char)p_bs->Buffer[1];
1409 p_bs->Buffer = p_bs->Buffer + 2;
1410
1411 break;
1412
1413 case 2:
1414 nal_size_high16 = ( p_bs->Buffer[0] << 8) + p_bs->Buffer[1];
1415 nal_size = nal_size_high16;
1416 nalu_info = (unsigned char)p_bs->Buffer[2];
1417 p_bs->Buffer = p_bs->Buffer + 3;
1418
1419 break;
1420
1421 case 4:
1422 nal_size_high16 = ( p_bs->Buffer[0] << 8) + p_bs->Buffer[1];
1423 nal_size_low16 = ( p_bs->Buffer[2] << 8) + p_bs->Buffer[3];
1424 nal_size = ( nal_size_high16 << 16) + nal_size_low16;
1425 nalu_info = (unsigned char)p_bs->Buffer[4];
1426 p_bs->Buffer = p_bs->Buffer + 5;
1427
1428 break;
1429 }
1430
1431 p_bs->bitPos = 0;
1432 p_bs->lastTotalBits = 0;
1433 p_bs->numBitsInBuffer =
1434 ( inbuf_size - frame_size - instance->m_Num_Bytes_NALUnitLength - 1)
1435 << 3;
1436 p_bs->readableBytesInBuffer =
1437 inbuf_size - frame_size - instance->m_Num_Bytes_NALUnitLength - 1;
1438
1439 p_bs->ui32TempBuff = 0;
1440 p_bs->i8BitCnt = 0;
1441 p_bs->pui8BfrPtr = (M4OSA_Int8 *)p_bs->Buffer;
1442 p_bs->ui32LastTwoBytes = 0xFFFFFFFF;
1443
1444 H264MCS_getBits(p_bs, 0);
1445
1446 frame_size += nal_size + instance->m_Num_Bytes_NALUnitLength;
1447
1448 forbidden_bit = ( nalu_info >> 7) & 1;
1449 nal_ref_idc = ( nalu_info >> 5) & 3;
1450 nal_unit_type = (nalu_info) &0x1f;
1451
1452 if( nal_unit_type == 8 )
1453 {
1454 M4OSA_TRACE1_0("H264MCS_ProcessSPS_PPS() Error: PPS");
1455 return err;
1456 }
1457
1458 if( nal_unit_type == 7 )
1459 {
1460 /*SPS Packet */
1461 M4OSA_TRACE1_0("H264MCS_ProcessSPS_PPS() Error: SPS");
1462 return err;
1463 }
1464
1465 if( ( nal_unit_type == 1) || (nal_unit_type == 5) )
1466 {
1467 first_mb_in_slice = H264MCS_DecVLCReadExpGolombCode(p_bs);
1468 slice_type = H264MCS_DecVLCReadExpGolombCode(p_bs);
1469 pic_parameter_set_id = H264MCS_DecVLCReadExpGolombCode(p_bs);
1470 break;
1471 }
1472 }
1473
1474 lActiveSPSID_Clip = Clip_SPSID_in_PPS[pic_parameter_set_id];
1475
1476 instance->final_SPS_ID = lActiveSPSID_Clip;
1477 /* Do we need to add encoder PPS to clip PPS */
1478
1479 lClipDSI = lClipDSI_PPS_start;
1480
1481 for ( cnt = 0; cnt < instance->m_encoder_PPS_Cnt; cnt++ )
1482 {
1483 lSize = ( lClipDSI[0] << 8) + lClipDSI[1];
1484 lClipDSI = lClipDSI + 2;
1485
1486 if( lActiveSPSID_Clip == Clip_SPSID_in_PPS[Clip_PPSID[cnt]] )
1487 {
1488 lPPS_Buffer = lClipDSI + 1;
1489 lPPS_Buffer_Size = lSize - 1;
1490
1491 p_bs->Buffer = (M4OSA_UInt8 *)(lClipDSI + 1);
1492 DecBitStreamReset_MCS(p_bs, lSize - 1);
1493
1494 Clip_PPSID[cnt] = H264MCS_DecVLCReadExpGolombCode(p_bs);
1495 Clip_UsedPPSID[Clip_SPSID[cnt]] = 1;
1496 Clip_SPSID_in_PPS[cnt] = H264MCS_DecVLCReadExpGolombCode(p_bs);
1497 lClipPPSRemBits = ( lSize - 1) << 3;
1498 lClipPPSRemBits -= p_bs->bitPos;
1499
1500 temp = lClipDSI[lSize - 1];
1501
1502 cnt1 = 0;
1503
1504 while( ( temp & 0x1) == 0 )
1505 {
1506 cnt1++;
1507 temp = temp >> 1;
1508 }
1509 cnt1++;
1510 lClipPPSRemBits -= cnt1;
1511
1512 lSize1 = instance->m_encoderPPSSize - 1;
1513 p_bs1->Buffer = (M4OSA_UInt8 *)(instance->m_pEncoderPPS + 1);
1514 DecBitStreamReset_MCS(p_bs1, lSize1);
1515
1516 lEncoder_PPSID = H264MCS_DecVLCReadExpGolombCode(p_bs1);
1517 lEncoder_SPSID = H264MCS_DecVLCReadExpGolombCode(p_bs1);
1518
1519 lEncoderPPSRemBits = ( lSize1) << 3;
1520 lEncoderPPSRemBits -= p_bs1->bitPos;
1521
1522 temp = instance->m_pEncoderPPS[lSize1];
1523
1524 cnt1 = 0;
1525
1526 while( ( temp & 0x1) == 0 )
1527 {
1528 cnt1++;
1529 temp = temp >> 1;
1530 }
1531 cnt1++;
1532 lEncoderPPSRemBits -= cnt1;
1533
1534 if( lEncoderPPSRemBits == lClipPPSRemBits )
1535 {
1536 while( lEncoderPPSRemBits > 8 )
1537 {
1538 temp1 = H264MCS_getBits(p_bs, 8);
1539 temp2 = H264MCS_getBits(p_bs1, 8);
1540 lEncoderPPSRemBits = lEncoderPPSRemBits - 8;
1541
1542 if( temp1 != temp2 )
1543 {
1544 break;
1545 }
1546 }
1547
1548 if( lEncoderPPSRemBits < 8 )
1549 {
1550 if( lEncoderPPSRemBits )
1551 {
1552 temp1 = H264MCS_getBits(p_bs, lEncoderPPSRemBits);
1553 temp2 = H264MCS_getBits(p_bs1, lEncoderPPSRemBits);
1554
1555 if( temp1 == temp2 )
1556 {
1557 lFound = 1;
1558 }
1559 }
1560 else
1561 {
1562 lFound = 1;
1563 }
1564 }
1565 break;
1566 }
1567 }
1568
1569 lClipDSI = lClipDSI + lSize;
1570 }
1571
1572 /* Form the final SPS and PPS data */
1573
1574 if( lFound == 1 )
1575 {
1576 /* No need to add PPS */
1577 instance->final_PPS_ID = Clip_PPSID[cnt];
1578
1579 instance->m_pFinalDSI =
1580 (M4OSA_UInt8 *)M4OSA_32bitAlignedMalloc(instance->m_decoderSpecificInfoSize,
1581 M4MCS, (M4OSA_Char *)"instance->m_pFinalDSI");
1582
1583 if( instance->m_pFinalDSI == M4OSA_NULL )
1584 {
1585 M4OSA_TRACE1_0("instance->m_pFinalDSI: allocation error");
1586 return M4ERR_ALLOC;
1587 }
1588
1589 instance->m_pFinalDSISize = instance->m_decoderSpecificInfoSize;
1590 memcpy((void *)instance->m_pFinalDSI,
1591 (void *)instance->m_pDecoderSpecificInfo,
1592 instance->m_decoderSpecificInfoSize);
1593 }
1594 else
1595 {
1596 /* ADD PPS */
1597 /* find the free PPS ID */
1598
1599 cnt = 0;
1600
1601 while( Clip_UsedPPSID[cnt] )
1602 {
1603 cnt++;
1604 }
1605 instance->final_PPS_ID = cnt;
1606
1607 size = instance->m_decoderSpecificInfoSize + instance->m_encoderPPSSize
1608 + 10;
1609
1610 instance->m_pFinalDSI = (M4OSA_UInt8 *)M4OSA_32bitAlignedMalloc(size, M4MCS,
1611 (M4OSA_Char *)"instance->m_pFinalDSI");
1612
1613 if( instance->m_pFinalDSI == M4OSA_NULL )
1614 {
1615 M4OSA_TRACE1_0("instance->m_pFinalDSI: allocation error");
1616 return M4ERR_ALLOC;
1617 }
1618
1619 memcpy((void *)instance->m_pFinalDSI,
1620 (void *)instance->m_pDecoderSpecificInfo,
1621 instance->m_decoderSpecificInfoSize);
1622
1623 temp = instance->m_pFinalDSI[lClipDSI_PPS_offset];
1624 temp = temp + 1;
1625 instance->m_pFinalDSI[lClipDSI_PPS_offset] = temp;
1626
1627 //temp = instance->m_pEncoderPPS[0];
1628 lSize1 = instance->m_encoderPPSSize - 1;
1629 p_bs1->Buffer = (M4OSA_UInt8 *)(instance->m_pEncoderPPS + 1);
1630 DecBitStreamReset_MCS(p_bs1, lSize1);
1631
1632 lEncoder_PPSID = H264MCS_DecVLCReadExpGolombCode(p_bs1);
1633 lEncoder_SPSID = H264MCS_DecVLCReadExpGolombCode(p_bs1);
1634
1635 lEncoderPPSRemBits = ( lSize1) << 3;
1636 lEncoderPPSRemBits -= p_bs1->bitPos;
1637
1638 temp = instance->m_pEncoderPPS[lSize1];
1639
1640 cnt1 = 0;
1641
1642 while( ( temp & 0x1) == 0 )
1643 {
1644 cnt1++;
1645 temp = temp >> 1;
1646 }
1647 cnt1++;
1648 lEncoderPPSRemBits -= cnt1;
1649
1650 instance->m_pFinalDSI[instance->m_decoderSpecificInfoSize + 2] =
1651 instance->m_pEncoderPPS[0];
1652
1653 NSWAVCMCS_initBitstream(&instance->encbs);
1654 instance->encbs.streamBuffer =
1655 &(instance->m_pFinalDSI[instance->m_decoderSpecificInfoSize + 3]);
1656 lPPS_Buffer = instance->encbs.streamBuffer;
1657
1658 NSWAVCMCS_uExpVLC(&instance->encbs, instance->final_PPS_ID);
1659 NSWAVCMCS_uExpVLC(&instance->encbs, instance->final_SPS_ID);
1660
1661 while( lEncoderPPSRemBits > 8 )
1662 {
1663 temp = H264MCS_getBits(p_bs1, 8);
1664 NSWAVCMCS_putBits(&instance->encbs, temp, 8);
1665 lEncoderPPSRemBits = lEncoderPPSRemBits - 8;
1666 }
1667
1668 if( lEncoderPPSRemBits )
1669 {
1670 temp = H264MCS_getBits(p_bs1, lEncoderPPSRemBits);
1671 NSWAVCMCS_putBits(&instance->encbs, temp, lEncoderPPSRemBits);
1672 }
1673 NSWAVCMCS_putRbspTbits(&instance->encbs);
1674
1675 temp = instance->encbs.byteCnt;
1676 lPPS_Buffer_Size = temp;
1677 temp = temp + 1;
1678
1679 instance->m_pFinalDSI[instance->m_decoderSpecificInfoSize] =
1680 ( temp >> 8) & 0xFF;
1681 instance->m_pFinalDSI[instance->m_decoderSpecificInfoSize + 1] =
1682 (temp) &0xFF;
1683 instance->m_pFinalDSISize =
1684 instance->m_decoderSpecificInfoSize + 2 + temp;
1685 }
1686
1687 /* Decode the clip SPS */
1688
1689 lClipDSI = instance->m_pDecoderSpecificInfo + 6;
1690
1691 lClipDSI_PPS_offset = 6;
1692
1693 for ( cnt = 0; cnt < instance->m_encoder_SPS_Cnt; cnt++ )
1694 {
1695 lSize = ( lClipDSI[0] << 8) + lClipDSI[1];
1696 lClipDSI = lClipDSI + 2;
1697
1698 if( Clip_SPSID[cnt] == instance->final_SPS_ID )
1699 {
1700 p_bs->Buffer = (M4OSA_UInt8 *)(lClipDSI + 1);
1701 DecBitStreamReset_MCS(p_bs, lSize - 1);
1702
1703 err = DecSPSMCS(p_bs, &instance->clip_sps);
1704 if(err != M4NO_ERROR) {
1705 return M4ERR_PARAMETER;
1706 }
1707
1708 //Clip_SPSID[cnt] = H264MCS_DecVLCReadExpGolombCode(p_bs);
1709 //Clip_UsedSPSID[Clip_SPSID[cnt]] = 1;
1710 break;
1711 }
1712
1713 lClipDSI = lClipDSI + lSize;
1714 }
1715
1716 /* Decode encoder SPS */
1717 p_bs->Buffer = (M4OSA_UInt8 *)(instance->m_pEncoderSPS + 1);
1718 DecBitStreamReset_MCS(p_bs, instance->m_encoderSPSSize - 1);
1719 err = DecSPSMCS(p_bs, &instance->encoder_sps);
1720 if(err != M4NO_ERROR) {
1721 return M4ERR_PARAMETER;
1722 }
1723
1724 if( instance->encoder_sps.num_ref_frames
1725 > instance->clip_sps.num_ref_frames )
1726 {
1727 return 100; //not supported
1728 }
1729
1730 p_bs->Buffer = (M4OSA_UInt8 *)lPPS_Buffer;
1731 DecBitStreamReset_MCS(p_bs, lPPS_Buffer_Size);
1732 DecPPSMCS(p_bs, &instance->encoder_pps);
1733
1734 instance->frame_count = 0;
1735 instance->frame_mod_count =
1736 1 << (instance->clip_sps.log2_max_frame_num_minus4 + 4);
1737
1738 instance->POC_lsb = 0;
1739 instance->POC_lsb_mod =
1740 1 << (instance->clip_sps.log2_max_pic_order_cnt_lsb_minus4 + 4);
1741
1742 return M4NO_ERROR;
1743 }
1744
H264MCS_ProcessNALU(NSWAVC_MCS_t * ainstance,M4OSA_UInt8 * inbuff,M4OSA_Int32 inbuf_size,M4OSA_UInt8 * outbuff,M4OSA_Int32 * outbuf_size)1745 M4OSA_ERR H264MCS_ProcessNALU( NSWAVC_MCS_t *ainstance, M4OSA_UInt8 *inbuff,
1746 M4OSA_Int32 inbuf_size, M4OSA_UInt8 *outbuff,
1747 M4OSA_Int32 *outbuf_size )
1748 {
1749 ComBitStreamMCS_t *p_bs, bs;
1750 NSWAVC_MCS_t *instance;
1751 M4OSA_UInt8 nalu_info;
1752 M4OSA_Int32 forbidden_bit, nal_ref_idc, nal_unit_type;
1753 M4OSA_Int32 first_mb_in_slice, slice_type, pic_parameter_set_id, frame_num;
1754 M4OSA_Int32 seq_parameter_set_id;
1755 M4OSA_UInt8 temp1, temp2, temp3, temp4;
1756 M4OSA_Int32 temp_frame_num;
1757 M4OSA_Int32 bitstoDiacard, bytes;
1758 M4OSA_UInt32 mask_bits = 0xFFFFFFFF;
1759 M4OSA_Int32 new_bytes, init_bit_pos;
1760 M4OSA_UInt32 nal_size;
1761 M4OSA_UInt32 cnt;
1762 M4OSA_UInt32 outbuffpos = 0;
1763 //#ifndef DGR_FIX // + new
1764 M4OSA_UInt32 nal_size_low16, nal_size_high16;
1765 //#endif // + end new
1766 M4OSA_UInt32 frame_size = 0;
1767 M4OSA_UInt32 temp = 0;
1768 M4OSA_ERR err = M4NO_ERROR;
1769 M4OSA_UInt8 *buff;
1770
1771 p_bs = &bs;
1772 instance = (NSWAVC_MCS_t *)ainstance;
1773 M4OSA_DEBUG_IF2((M4OSA_NULL == instance), M4ERR_PARAMETER,
1774 "H264MCS_ProcessNALU: instance is M4OSA_NULL");
1775
1776 if( instance->is_done )
1777 return err;
1778
1779 inbuff[0] = 0x00;
1780 inbuff[1] = 0x00;
1781 inbuff[2] = 0x00;
1782 inbuff[3] = 0x01;
1783
1784
1785 while( (M4OSA_Int32)frame_size < inbuf_size )
1786 {
1787 mask_bits = 0xFFFFFFFF;
1788 p_bs->Buffer = (M4OSA_UInt8 *)(inbuff + frame_size);
1789
1790
1791 nalu_info = (unsigned char)p_bs->Buffer[4];
1792
1793 outbuff[outbuffpos] = p_bs->Buffer[0];
1794 outbuff[outbuffpos + 1] = p_bs->Buffer[1];
1795 outbuff[outbuffpos + 2] = p_bs->Buffer[2];
1796 outbuff[outbuffpos + 3] = p_bs->Buffer[3];
1797 outbuff[outbuffpos + 4] = p_bs->Buffer[4];
1798
1799 p_bs->Buffer = p_bs->Buffer + 5;
1800
1801 p_bs->bitPos = 0;
1802 p_bs->lastTotalBits = 0;
1803 p_bs->numBitsInBuffer = ( inbuf_size - frame_size - 5) << 3;
1804 p_bs->readableBytesInBuffer = inbuf_size - frame_size - 5;
1805
1806 p_bs->ui32TempBuff = 0;
1807 p_bs->i8BitCnt = 0;
1808 p_bs->pui8BfrPtr = (M4OSA_Int8 *)p_bs->Buffer;
1809 p_bs->ui32LastTwoBytes = 0xFFFFFFFF;
1810
1811 H264MCS_getBits(p_bs, 0);
1812
1813
1814
1815 nal_size = inbuf_size - frame_size - 4;
1816 buff = inbuff + frame_size + 4;
1817
1818 while( nal_size > 4 )
1819 {
1820 if( ( buff[0] == 0x00) && (buff[1] == 0x00) && (buff[2] == 0x00)
1821 && (buff[3] == 0x01) )
1822 {
1823 break;
1824 }
1825 buff = buff + 1;
1826 nal_size = nal_size - 1;
1827 }
1828
1829 if( nal_size <= 4 )
1830 {
1831 nal_size = 0;
1832 }
1833 nal_size = ( inbuf_size - frame_size - 4) - nal_size;
1834
1835 // M4OSA_TRACE1_3("H264MCS_ProcessNALU frame input buff size = %d current position
1836 //= %d nal size = %d",
1837 // inbuf_size, frame_size, nal_size + 4);
1838 frame_size += nal_size + 4;
1839
1840
1841
1842 forbidden_bit = ( nalu_info >> 7) & 1;
1843 nal_ref_idc = ( nalu_info >> 5) & 3;
1844 nal_unit_type = (nalu_info) &0x1f;
1845
1846 if( nal_unit_type == 5 )
1847 {
1848 /*IDR/PPS Packet - Do nothing*/
1849 instance->is_done = 1;
1850 return err;
1851 }
1852
1853 NSWAVCMCS_initBitstream(&instance->encbs);
1854 instance->encbs.streamBuffer = outbuff + outbuffpos + 5;
1855
1856 if( nal_unit_type == 8 )
1857 {
1858 M4OSA_TRACE1_0("H264MCS_ProcessNALU() Error: PPS");
1859 return err;
1860 }
1861
1862 if( nal_unit_type == 7 )
1863 {
1864 /*SPS Packet */
1865 M4OSA_TRACE1_0("H264MCS_ProcessNALU() Error: SPS");
1866 return 0;
1867 }
1868
1869 if( (nal_unit_type == 5) )
1870 {
1871 instance->frame_count = 0;
1872 instance->POC_lsb = 0;
1873 }
1874
1875 if( (nal_unit_type == 1) )
1876 {
1877 first_mb_in_slice = H264MCS_DecVLCReadExpGolombCode(p_bs);
1878 NSWAVCMCS_uExpVLC(&instance->encbs, first_mb_in_slice);
1879
1880 slice_type = H264MCS_DecVLCReadExpGolombCode(p_bs);
1881 NSWAVCMCS_uExpVLC(&instance->encbs, slice_type);
1882
1883 pic_parameter_set_id = H264MCS_DecVLCReadExpGolombCode(p_bs);
1884 NSWAVCMCS_uExpVLC(&instance->encbs, pic_parameter_set_id);
1885
1886 temp = H264MCS_getBits(p_bs,
1887 instance->clip_sps.log2_max_frame_num_minus4 + 4);
1888 NSWAVCMCS_putBits(&instance->encbs, instance->frame_count,
1889 instance->clip_sps.log2_max_frame_num_minus4 + 4);
1890
1891 // In Baseline Profile: frame_mbs_only_flag should be ON
1892
1893 if( nal_unit_type == 5 )
1894 {
1895 temp = H264MCS_DecVLCReadExpGolombCode(p_bs);
1896 NSWAVCMCS_uExpVLC(&instance->encbs, temp);
1897 }
1898
1899 if( instance->clip_sps.pic_order_cnt_type == 0 )
1900 {
1901 temp = H264MCS_getBits(p_bs,
1902 instance->clip_sps.log2_max_pic_order_cnt_lsb_minus4
1903 + 4);
1904 NSWAVCMCS_putBits(&instance->encbs, instance->POC_lsb,
1905 instance->clip_sps.log2_max_pic_order_cnt_lsb_minus4 + 4);
1906 }
1907
1908 if( ( instance->clip_sps.pic_order_cnt_type == 1)
1909 && (instance->clip_sps.delta_pic_order_always_zero_flag) )
1910 {
1911 temp = H264MCS_DecVLCReadSignedExpGolombCode(p_bs);
1912 NSWAVCMCS_sExpVLC(&instance->encbs, temp);
1913 }
1914
1915 cnt = p_bs->bitPos & 0x7;
1916
1917 if( cnt )
1918 {
1919 cnt = 8 - cnt;
1920 temp = H264MCS_getBits(p_bs, cnt);
1921 NSWAVCMCS_putBits(&instance->encbs, temp, cnt);
1922 }
1923
1924 cnt = p_bs->bitPos >> 3;
1925
1926 while( cnt < (nal_size - 2) )
1927 {
1928 temp = H264MCS_getBits(p_bs, 8);
1929 NSWAVCMCS_putBits(&instance->encbs, temp, 8);
1930 cnt = p_bs->bitPos >> 3;
1931 }
1932
1933 temp = H264MCS_getBits(p_bs, 8);
1934
1935 if( temp != 0 )
1936 {
1937 cnt = 0;
1938
1939 while( ( temp & 0x1) == 0 )
1940 {
1941 cnt++;
1942 temp = temp >> 1;
1943 }
1944 cnt++;
1945 temp = temp >> 1;
1946
1947 if( 8 - cnt )
1948 {
1949 NSWAVCMCS_putBits(&instance->encbs, temp, (8 - cnt));
1950 }
1951
1952 NSWAVCMCS_putRbspTbits(&instance->encbs);
1953 }
1954 else
1955 {
1956 if( instance->encbs.bitPos % 8 )
1957 {
1958 NSWAVCMCS_putBits(&instance->encbs, 0,
1959 (8 - instance->encbs.bitPos % 8));
1960 }
1961 }
1962
1963 temp = instance->encbs.byteCnt;
1964 temp = temp + 1;
1965
1966 outbuff[outbuffpos] = (M4OSA_UInt8)(( temp >> 24) & 0xFF);
1967 outbuff[outbuffpos + 1] = (M4OSA_UInt8)(( temp >> 16) & 0xFF);
1968 outbuff[outbuffpos + 2] = (M4OSA_UInt8)(( temp >> 8) & 0xFF);
1969 outbuff[outbuffpos + 3] = (M4OSA_UInt8)((temp) &0xFF);
1970 outbuffpos = outbuffpos + temp + 4;
1971 }
1972 else
1973 {
1974 p_bs->Buffer = p_bs->Buffer - 5;
1975 memcpy((void *) &outbuff[outbuffpos],
1976 (void *)p_bs->Buffer, nal_size + 4);
1977
1978 outbuff[outbuffpos] = (M4OSA_UInt8)((nal_size >> 24)& 0xFF);
1979 outbuff[outbuffpos + 1] = (M4OSA_UInt8)((nal_size >> 16)& 0xFF);;
1980 outbuff[outbuffpos + 2] = (M4OSA_UInt8)((nal_size >> 8)& 0xFF);;
1981 outbuff[outbuffpos + 3] = (M4OSA_UInt8)((nal_size)& 0xFF);;
1982
1983 outbuffpos = outbuffpos + nal_size + 4;
1984 }
1985 }
1986
1987 *outbuf_size = outbuffpos;
1988
1989 instance->POC_lsb = instance->POC_lsb + 1;
1990
1991 if( instance->POC_lsb == instance->POC_lsb_mod )
1992 {
1993 instance->POC_lsb = 0;
1994 }
1995 instance->frame_count = instance->frame_count + 1;
1996
1997 if( instance->frame_count == instance->frame_mod_count )
1998 {
1999 instance->frame_count = 0;
2000 }
2001 return M4NO_ERROR;
2002 }
2003
M4MCS_convetFromByteStreamtoNALStream(M4OSA_UInt8 * inbuff,M4OSA_UInt32 inbuf_size)2004 M4OSA_ERR M4MCS_convetFromByteStreamtoNALStream( M4OSA_UInt8 *inbuff,
2005 M4OSA_UInt32 inbuf_size )
2006 {
2007 M4OSA_ERR err = M4NO_ERROR;
2008 M4OSA_UInt32 framesize = 0;
2009 M4OSA_UInt32 nal_size =0;
2010 M4OSA_UInt8 *buff;
2011
2012
2013 while(framesize < inbuf_size)
2014 {
2015 nal_size = inbuf_size - framesize - 4;
2016 buff = inbuff + framesize + 4;
2017
2018 while(nal_size > 4){
2019 if((buff[0] == 0x00) &&
2020 (buff[1] == 0x00) &&
2021 (buff[2] == 0x00) &&
2022 (buff[3] == 0x01)){
2023 break;
2024 }
2025 buff = buff + 1;
2026 nal_size = nal_size -1;
2027 }
2028
2029 if(nal_size <= 4){
2030 nal_size = 0;
2031 }
2032 nal_size = (inbuf_size - framesize - 4) - nal_size;
2033
2034 inbuff[framesize + 0] = (M4OSA_UInt8)((nal_size >> 24)& 0xFF);
2035 inbuff[framesize + 1] = (M4OSA_UInt8)((nal_size >> 16)& 0xFF);
2036 inbuff[framesize + 2] = (M4OSA_UInt8)((nal_size >> 8)& 0xFF);
2037 inbuff[framesize + 3] = (M4OSA_UInt8)((nal_size )& 0xFF);
2038 framesize += nal_size + 4;
2039
2040 M4OSA_TRACE1_2("M4MCS_convetFromByteStreamtoNALStream framesize = %x nalsize = %x",
2041 framesize, nal_size)
2042 }
2043
2044 return err;
2045 }
2046
2047
H264MCS_Freeinstance(NSWAVC_MCS_t * instance)2048 M4OSA_ERR H264MCS_Freeinstance( NSWAVC_MCS_t *instance )
2049 {
2050 M4OSA_ERR err = M4NO_ERROR;
2051 M4OSA_DEBUG_IF2((M4OSA_NULL == instance), M4ERR_PARAMETER,
2052 "H264MCS_Freeinstance: instance is M4OSA_NULL");
2053
2054 if( M4OSA_NULL != instance->encoder_pps.slice_group_id )
2055 {
2056 free(instance->encoder_pps.slice_group_id);
2057 }
2058
2059 if( M4OSA_NULL != instance->p_encoder_sps )
2060 {
2061 free(instance->p_encoder_sps);
2062 instance->p_encoder_sps = M4OSA_NULL;
2063 }
2064
2065 if( M4OSA_NULL != instance->p_encoder_pps )
2066 {
2067 free(instance->p_encoder_pps);
2068 instance->p_encoder_pps = M4OSA_NULL;
2069 }
2070
2071 if( M4OSA_NULL != instance->m_pFinalDSI )
2072 {
2073 free(instance->m_pFinalDSI);
2074 instance->m_pFinalDSI = M4OSA_NULL;
2075 }
2076
2077 if( M4OSA_NULL != instance )
2078 {
2079 free(instance);
2080 instance = M4OSA_NULL;
2081 }
2082
2083 return err;
2084 }
2085 /**
2086 ******************************************************************************
2087 * M4OSA_ERR M4MCS_getVersion(M4_VersionInfo* pVersionInfo);
2088 * @brief Get the MCS version.
2089 * @note Can be called anytime. Do not need any context.
2090 * @param pVersionInfo (OUT) Pointer to a version info structure
2091 * @return M4NO_ERROR: No error
2092 * @return M4ERR_PARAMETER: pVersionInfo is M4OSA_NULL (If Debug Level >= 2)
2093 ******************************************************************************
2094 */
M4MCS_getVersion(M4_VersionInfo * pVersionInfo)2095 M4OSA_ERR M4MCS_getVersion( M4_VersionInfo *pVersionInfo )
2096 {
2097 M4OSA_TRACE3_1("M4MCS_getVersion called with pVersionInfo=0x%x",
2098 pVersionInfo);
2099
2100 /**
2101 * Check input parameters */
2102 M4OSA_DEBUG_IF2((M4OSA_NULL == pVersionInfo), M4ERR_PARAMETER,
2103 "M4MCS_getVersion: pVersionInfo is M4OSA_NULL");
2104
2105 pVersionInfo->m_major = M4MCS_VERSION_MAJOR;
2106 pVersionInfo->m_minor = M4MCS_VERSION_MINOR;
2107 pVersionInfo->m_revision = M4MCS_VERSION_REVISION;
2108
2109 /**
2110 * Return with no error */
2111 M4OSA_TRACE3_0("M4MCS_getVersion(): returning M4NO_ERROR");
2112 return M4NO_ERROR;
2113 }
2114
2115 /**
2116 ******************************************************************************
2117 * @brief Initializes the MCS (allocates an execution context).
2118 * @note
2119 * @param pContext (OUT) Pointer on the MCS context to allocate
2120 * @param pFileReadPtrFct (IN) Pointer to OSAL file reader functions
2121 * @param pFileWritePtrFct (IN) Pointer to OSAL file writer functions
2122 * @return M4NO_ERROR: No error
2123 * @return M4ERR_PARAMETER: At least one parameter is M4OSA_NULL (If Debug Level >= 2)
2124 * @return M4ERR_ALLOC: There is no more available memory
2125 ******************************************************************************
2126 */
2127
M4MCS_init(M4MCS_Context * pContext,M4OSA_FileReadPointer * pFileReadPtrFct,M4OSA_FileWriterPointer * pFileWritePtrFct)2128 M4OSA_ERR M4MCS_init( M4MCS_Context *pContext,
2129 M4OSA_FileReadPointer *pFileReadPtrFct,
2130 M4OSA_FileWriterPointer *pFileWritePtrFct )
2131 {
2132 M4MCS_InternalContext *pC = M4OSA_NULL;
2133 M4OSA_ERR err;
2134
2135 M4OSA_TRACE3_3(
2136 "M4MCS_init called with pContext=0x%x, pFileReadPtrFct=0x%x, pFileWritePtrFct=0x%x",
2137 pContext, pFileReadPtrFct, pFileWritePtrFct);
2138
2139 /**
2140 * Check input parameters */
2141 M4OSA_DEBUG_IF2((M4OSA_NULL == pContext), M4ERR_PARAMETER,
2142 "M4MCS_init: pContext is M4OSA_NULL");
2143 M4OSA_DEBUG_IF2((M4OSA_NULL == pFileReadPtrFct), M4ERR_PARAMETER,
2144 "M4MCS_init: pFileReadPtrFct is M4OSA_NULL");
2145 M4OSA_DEBUG_IF2((M4OSA_NULL == pFileWritePtrFct), M4ERR_PARAMETER,
2146 "M4MCS_init: pFileWritePtrFct is M4OSA_NULL");
2147
2148 /**
2149 * Allocate the MCS context and return it to the user */
2150 pC = (M4MCS_InternalContext *)M4OSA_32bitAlignedMalloc(sizeof(M4MCS_InternalContext),
2151 M4MCS, (M4OSA_Char *)"M4MCS_InternalContext");
2152 *pContext = pC;
2153
2154 if( M4OSA_NULL == pC )
2155 {
2156 M4OSA_TRACE1_0(
2157 "M4MCS_init(): unable to allocate M4MCS_InternalContext, returning M4ERR_ALLOC");
2158 return M4ERR_ALLOC;
2159 }
2160
2161 /**
2162 * Init the context. All pointers must be initialized to M4OSA_NULL
2163 * because CleanUp() can be called just after Init(). */
2164 pC->State = M4MCS_kState_CREATED;
2165 pC->pOsaFileReadPtr = pFileReadPtrFct;
2166 pC->pOsaFileWritPtr = pFileWritePtrFct;
2167 pC->VideoState = M4MCS_kStreamState_NOSTREAM;
2168 pC->AudioState = M4MCS_kStreamState_NOSTREAM;
2169 pC->noaudio = M4OSA_FALSE;
2170 pC->novideo = M4OSA_FALSE;
2171 pC->uiProgress = 0;
2172
2173 /**
2174 * Reader stuff */
2175 pC->pInputFile = M4OSA_NULL;
2176 pC->InputFileType = M4VIDEOEDITING_kFileType_Unsupported;
2177 pC->bFileOpenedInFastMode = M4OSA_FALSE;
2178 pC->pReaderContext = M4OSA_NULL;
2179 pC->pReaderVideoStream = M4OSA_NULL;
2180 pC->pReaderAudioStream = M4OSA_NULL;
2181 pC->bUnsupportedVideoFound = M4OSA_FALSE;
2182 pC->bUnsupportedAudioFound = M4OSA_FALSE;
2183 pC->iAudioCtsOffset = 0;
2184 /* First temporary video AU to have more precise end video cut*/
2185 pC->ReaderVideoAU1.m_structSize = 0;
2186 /* Second temporary video AU to have more precise end video cut*/
2187 pC->ReaderVideoAU2.m_structSize = 0;
2188 pC->ReaderAudioAU1.m_structSize = 0;
2189 pC->ReaderAudioAU2.m_structSize = 0;
2190 pC->m_audioAUDuration = 0;
2191 pC->m_pDataAddress1 = M4OSA_NULL;
2192 pC->m_pDataAddress2 = M4OSA_NULL;
2193 /* First temporary video AU data to have more precise end video cut*/
2194 pC->m_pDataVideoAddress1 = M4OSA_NULL;
2195 /* Second temporary video AU data to have more precise end video cut*/
2196 pC->m_pDataVideoAddress2 = M4OSA_NULL;
2197
2198 /**
2199 * Video decoder stuff */
2200 pC->pViDecCtxt = M4OSA_NULL;
2201 pC->dViDecStartingCts = 0.0;
2202 pC->iVideoBeginDecIncr = 0;
2203 pC->dViDecCurrentCts = 0.0;
2204 pC->dCtsIncrement = 0.0;
2205 pC->isRenderDup = M4OSA_FALSE;
2206
2207 /**
2208 * Video encoder stuff */
2209 pC->pViEncCtxt = M4OSA_NULL;
2210 pC->pPreResizeFrame = M4OSA_NULL;
2211 pC->uiEncVideoBitrate = 0;
2212 pC->encoderState = M4MCS_kNoEncoder;
2213
2214 /**
2215 * Audio decoder stuff */
2216 pC->pAudioDecCtxt = M4OSA_NULL;
2217 pC->AudioDecBufferIn.m_dataAddress = M4OSA_NULL;
2218 pC->AudioDecBufferIn.m_bufferSize = 0;
2219 pC->AudioDecBufferOut.m_dataAddress = M4OSA_NULL;
2220 pC->AudioDecBufferOut.m_bufferSize = 0;
2221 pC->pPosInDecBufferOut = M4OSA_NULL;
2222 /**
2223 * Ssrc stuff */
2224 pC->pSsrcBufferIn = M4OSA_NULL;
2225 pC->pSsrcBufferOut = M4OSA_NULL;
2226 pC->pPosInSsrcBufferIn = M4OSA_NULL;
2227 pC->pPosInSsrcBufferOut = M4OSA_NULL;
2228 pC->iSsrcNbSamplIn = 0;
2229 pC->iSsrcNbSamplOut = 0;
2230 pC->SsrcScratch = M4OSA_NULL;
2231 pC->pLVAudioResampler = M4OSA_NULL;
2232 /**
2233 * Audio encoder */
2234 pC->pAudioEncCtxt = M4OSA_NULL;
2235 pC->pAudioEncDSI.infoSize = 0;
2236 pC->pAudioEncDSI.pInfo = M4OSA_NULL;
2237 pC->pAudioEncoderBuffer = M4OSA_NULL;
2238 pC->pPosInAudioEncoderBuffer = M4OSA_NULL;
2239 pC->audioEncoderGranularity = 0;
2240
2241 /**
2242 * Writer stuff */
2243 pC->pOutputFile = M4OSA_NULL;
2244 pC->pTemporaryFile = M4OSA_NULL;
2245 pC->pWriterContext = M4OSA_NULL;
2246 pC->uiVideoAUCount = 0;
2247 pC->uiVideoMaxAuSize = 0;
2248 pC->uiVideoMaxChunckSize = 0;
2249 pC->uiAudioAUCount = 0;
2250 pC->uiAudioMaxAuSize = 0;
2251
2252 pC->uiAudioCts = 0;
2253 pC->b_isRawWriter = M4OSA_FALSE;
2254 pC->pOutputPCMfile = M4OSA_NULL;
2255
2256 /* Encoding config */
2257 pC->EncodingVideoFormat = M4ENCODER_kNULL; /**< No format set yet */
2258 pC->EncodingWidth = 0; /**< No size set yet */
2259 pC->EncodingHeight = 0; /**< No size set yet */
2260 pC->EncodingVideoFramerate = 0; /**< No framerate set yet */
2261
2262 pC->uiBeginCutTime = 0; /**< No begin cut */
2263 pC->uiEndCutTime = 0; /**< No end cut */
2264 pC->uiMaxFileSize = 0; /**< No limit */
2265 pC->uiAudioBitrate =
2266 M4VIDEOEDITING_kUndefinedBitrate; /**< No bitrate set yet */
2267 pC->uiVideoBitrate =
2268 M4VIDEOEDITING_kUndefinedBitrate; /**< No bitrate set yet */
2269
2270 pC->WriterVideoStream.streamType = M4SYS_kVideoUnknown;
2271 pC->WriterVideoStreamInfo.Header.pBuf = M4OSA_NULL;
2272 pC->WriterAudioStream.streamType = M4SYS_kAudioUnknown;
2273
2274 pC->outputVideoTimescale = 0;
2275
2276 /*FB 2008/10/20: add media rendering parameter and AIR context to keep media aspect ratio*/
2277 pC->MediaRendering = M4MCS_kResizing;
2278 pC->m_air_context = M4OSA_NULL;
2279 /**/
2280
2281 /**
2282 * FlB 2009.03.04: add audio Effects*/
2283 pC->pEffects = M4OSA_NULL;
2284 pC->nbEffects = 0;
2285 pC->pActiveEffectNumber = -1;
2286 /**/
2287
2288 /*
2289 * Reset pointers for media and codecs interfaces */
2290 err = M4MCS_clearInterfaceTables(pC);
2291 M4ERR_CHECK_RETURN(err);
2292
2293 /*
2294 * Call the media and codecs subscription module */
2295 err = M4MCS_subscribeMediaAndCodec(pC);
2296 M4ERR_CHECK_RETURN(err);
2297
2298 #ifdef M4MCS_SUPPORT_STILL_PICTURE
2299 /**
2300 * Initialize the Still picture part of MCS*/
2301
2302 err = M4MCS_stillPicInit(pC, pFileReadPtrFct, pFileWritePtrFct);
2303 M4ERR_CHECK_RETURN(err);
2304
2305 pC->m_bIsStillPicture = M4OSA_FALSE;
2306
2307 #endif /*M4MCS_SUPPORT_STILL_PICTURE*/
2308
2309 pC->m_pInstance = M4OSA_NULL;
2310 pC->H264MCSTempBuffer = M4OSA_NULL;
2311 pC->H264MCSTempBufferSize = 0;
2312 pC->H264MCSTempBufferDataSize = 0;
2313 pC->bH264Trim = M4OSA_FALSE;
2314
2315 /* Flag to get the last decoded frame cts */
2316 pC->bLastDecodedFrameCTS = M4OSA_FALSE;
2317
2318 if( pC->m_pInstance == M4OSA_NULL )
2319 {
2320 err = H264MCS_Getinstance(&pC->m_pInstance);
2321 }
2322 pC->bExtOMXAudDecoder = M4OSA_FALSE;
2323
2324 /**
2325 * Return with no error */
2326 M4OSA_TRACE3_0("M4MCS_init(): returning M4NO_ERROR");
2327 return M4NO_ERROR;
2328 }
2329
2330 /**
2331 ******************************************************************************
2332 * M4OSA_ERR M4MCS_open(M4MCS_Context pContext, M4OSA_Void* pFileIn,
2333 * M4OSA_Void* pFileOut, M4OSA_Void* pTempFile);
2334 * @brief Set the MCS input and output files.
2335 * @note It opens the input file, but the output file is not created yet.
2336 * @param pContext (IN) MCS context
2337 * @param pFileIn (IN) Input file to transcode (The type of this parameter
2338 * (URL, pipe...) depends on the OSAL implementation).
2339 * @param mediaType (IN) Container type (.3gp,.amr,mp3 ...) of input file.
2340 * @param pFileOut (IN) Output file to create (The type of this parameter
2341 * (URL, pipe...) depends on the OSAL implementation).
2342 * @param pTempFile (IN) Temporary file for the constant memory writer to
2343 * store metadata ("moov.bin").
2344 * @return M4NO_ERROR: No error
2345 * @return M4ERR_PARAMETER: At least one parameter is M4OSA_NULL (debug only)
2346 * @return M4ERR_STATE: MCS is not in an appropriate state for this function to be called
2347 * @return M4ERR_ALLOC: There is no more available memory
2348 * @return M4ERR_FILE_NOT_FOUND: The input file has not been found
2349 * @return M4MCS_ERR_INVALID_INPUT_FILE: The input file is not a valid file, or is corrupted
2350 * @return M4MCS_ERR_INPUT_FILE_CONTAINS_NO_SUPPORTED_STREAM: The input file contains no
2351 * supported audio or video stream
2352 ******************************************************************************
2353 */
M4MCS_open(M4MCS_Context pContext,M4OSA_Void * pFileIn,M4VIDEOEDITING_FileType InputFileType,M4OSA_Void * pFileOut,M4OSA_Void * pTempFile)2354 M4OSA_ERR M4MCS_open( M4MCS_Context pContext, M4OSA_Void *pFileIn,
2355 M4VIDEOEDITING_FileType InputFileType, M4OSA_Void *pFileOut,
2356 M4OSA_Void *pTempFile )
2357 {
2358 M4MCS_InternalContext *pC = (M4MCS_InternalContext *)(pContext);
2359 M4OSA_ERR err;
2360
2361 M4READER_MediaFamily mediaFamily;
2362 M4_StreamHandler *pStreamHandler;
2363
2364 M4OSA_TRACE2_3(
2365 "M4MCS_open called with pContext=0x%x, pFileIn=0x%x, pFileOut=0x%x",
2366 pContext, pFileIn, pFileOut);
2367
2368 /**
2369 * Check input parameters */
2370 M4OSA_DEBUG_IF2((M4OSA_NULL == pContext), M4ERR_PARAMETER,
2371 "M4MCS_open: pContext is M4OSA_NULL");
2372 M4OSA_DEBUG_IF2((M4OSA_NULL == pFileIn), M4ERR_PARAMETER,
2373 "M4MCS_open: pFileIn is M4OSA_NULL");
2374
2375 if( ( InputFileType == M4VIDEOEDITING_kFileType_JPG)
2376 || (InputFileType == M4VIDEOEDITING_kFileType_PNG)
2377 || (InputFileType == M4VIDEOEDITING_kFileType_GIF)
2378 || (InputFileType == M4VIDEOEDITING_kFileType_BMP) )
2379 {
2380 #ifdef M4MCS_SUPPORT_STILL_PICTURE
2381 /**
2382 * Indicate that we must use the still picture functions*/
2383
2384 pC->m_bIsStillPicture = M4OSA_TRUE;
2385
2386 /**
2387 * Call the still picture MCS functions*/
2388 return M4MCS_stillPicOpen(pC, pFileIn, InputFileType, pFileOut);
2389
2390 #else
2391
2392 M4OSA_TRACE1_0(
2393 "M4MCS_open: Still picture is not supported with this version of MCS");
2394 return M4MCS_ERR_INPUT_FILE_CONTAINS_NO_SUPPORTED_STREAM;
2395
2396 #endif /*M4MCS_SUPPORT_STILL_PICTURE*/
2397
2398 }
2399
2400 /**
2401 * Check state automaton */
2402 if( M4MCS_kState_CREATED != pC->State )
2403 {
2404 M4OSA_TRACE1_1("M4MCS_open(): Wrong State (%d), returning M4ERR_STATE",
2405 pC->State);
2406 return M4ERR_STATE;
2407 }
2408
2409 /* Copy function input parameters into our context */
2410 pC->pInputFile = pFileIn;
2411 pC->InputFileType = InputFileType;
2412 pC->pOutputFile = pFileOut;
2413 pC->pTemporaryFile = pTempFile;
2414 pC->uiProgress = 0;
2415
2416 /***********************************/
2417 /* Open input file with the reader */
2418 /***********************************/
2419
2420 err = M4MCS_setCurrentReader(pContext, pC->InputFileType);
2421 M4ERR_CHECK_RETURN(err);
2422
2423 /**
2424 * Reset reader related variables */
2425 pC->VideoState = M4MCS_kStreamState_NOSTREAM;
2426 pC->AudioState = M4MCS_kStreamState_NOSTREAM;
2427 pC->pReaderVideoStream = M4OSA_NULL;
2428 pC->pReaderAudioStream = M4OSA_NULL;
2429
2430 /*******************************************************/
2431 /* Initializes the reader shell and open the data file */
2432 /*******************************************************/
2433 err = pC->m_pReader->m_pFctCreate(&pC->pReaderContext);
2434
2435 if( M4NO_ERROR != err )
2436 {
2437 M4OSA_TRACE1_1("M4MCS_open(): m_pReader->m_pFctCreate returns 0x%x",
2438 err);
2439 return err;
2440 }
2441
2442 /**
2443 * Link the reader interface to the reader context */
2444 pC->m_pReaderDataIt->m_readerContext = pC->pReaderContext;
2445
2446 /**
2447 * Set the reader shell file access functions */
2448 err = pC->m_pReader->m_pFctSetOption(pC->pReaderContext,
2449 M4READER_kOptionID_SetOsaFileReaderFctsPtr,
2450 (M4OSA_DataOption)pC->pOsaFileReadPtr);
2451
2452 if( M4NO_ERROR != err )
2453 {
2454 M4OSA_TRACE1_1("M4MCS_open(): m_pReader->m_pFctSetOption returns 0x%x",
2455 err);
2456 return err;
2457 }
2458
2459 #ifdef M4MCS_WITH_FAST_OPEN
2460
2461 if( M4OSA_FALSE == pC->bFileOpenedInFastMode )
2462 {
2463 M4OSA_Bool trueValue = M4OSA_TRUE;
2464
2465 /* For first call use fast open mode */
2466 err = pC->m_pReader->m_pFctSetOption(pC->pReaderContext,
2467 M4READER_3GP_kOptionID_FastOpenMode, &trueValue);
2468
2469 if( M4NO_ERROR == err )
2470 {
2471 pC->bFileOpenedInFastMode = M4OSA_TRUE;
2472 }
2473 else
2474 {
2475 M4OSA_TRACE1_1(
2476 "M4MCS_open(): M4READER_3GP_kOptionID_FastOpenMode returns 0x%x",
2477 err);
2478
2479 if( ( ( (M4OSA_UInt32)M4ERR_BAD_OPTION_ID) == err)
2480 || (( (M4OSA_UInt32)M4ERR_PARAMETER) == err) )
2481 {
2482 /* Not fatal, some readers may not support fast open mode */
2483 pC->bFileOpenedInFastMode = M4OSA_FALSE;
2484 }
2485 else
2486 return err;
2487 }
2488 }
2489 else
2490 {
2491 M4OSA_Bool falseValue = M4OSA_FALSE;
2492
2493 /* For second call use normal open mode */
2494 err = pC->m_pReader->m_pFctSetOption(pC->pReaderContext,
2495 M4READER_3GP_kOptionID_FastOpenMode, &falseValue);
2496 }
2497
2498 #endif /* M4MCS_WITH_FAST_OPEN */
2499
2500 /**
2501 * Open the input file */
2502
2503 err = pC->m_pReader->m_pFctOpen(pC->pReaderContext, pC->pInputFile);
2504
2505 if( M4NO_ERROR != err )
2506 {
2507 M4OSA_UInt32 uiDummy, uiCoreId;
2508 M4OSA_TRACE1_1("M4MCS_open(): m_pReader->m_pFctOpen returns 0x%x", err);
2509
2510 /**
2511 * If the error is from the core reader, we change it to a public VXS error */
2512 M4OSA_ERR_SPLIT(err, uiDummy, uiCoreId, uiDummy);
2513
2514 if( M4MP4_READER == uiCoreId )
2515 {
2516 M4OSA_TRACE1_0(
2517 "M4MCS_open(): returning M4MCS_ERR_INVALID_INPUT_FILE");
2518 return M4MCS_ERR_INVALID_INPUT_FILE;
2519 }
2520 return err;
2521 }
2522
2523 /**
2524 * Get the streams from the input file */
2525 while( M4NO_ERROR == err )
2526 {
2527 err =
2528 pC->m_pReader->m_pFctGetNextStream( pC->pReaderContext,
2529 &mediaFamily,
2530 &pStreamHandler);
2531
2532 /**
2533 * In case we found a BIFS stream or something else...*/
2534 if( ( err == ((M4OSA_UInt32)M4ERR_READER_UNKNOWN_STREAM_TYPE))
2535 || (err == ((M4OSA_UInt32)M4WAR_TOO_MUCH_STREAMS)) )
2536 {
2537 err = M4NO_ERROR;
2538 continue;
2539 }
2540
2541 if( M4NO_ERROR == err ) /**< One stream found */
2542 {
2543 /**
2544 * Found the first video stream */
2545 if( ( M4READER_kMediaFamilyVideo == mediaFamily)
2546 && (M4OSA_NULL == pC->pReaderVideoStream) )
2547 {
2548 if( ( M4DA_StreamTypeVideoH263 == pStreamHandler->m_streamType)
2549 || (M4DA_StreamTypeVideoMpeg4
2550 == pStreamHandler->m_streamType)
2551 || (M4DA_StreamTypeVideoMpeg4Avc
2552 == pStreamHandler->m_streamType) )
2553 {
2554 M4OSA_TRACE3_0(
2555 "M4MCS_open(): Found a H263 or MPEG-4 video stream in input 3gpp clip");
2556
2557 /**
2558 * Keep pointer to the video stream */
2559 pC->pReaderVideoStream =
2560 (M4_VideoStreamHandler *)pStreamHandler;
2561 pC->bUnsupportedVideoFound = M4OSA_FALSE;
2562 pStreamHandler->m_bStreamIsOK = M4OSA_TRUE;
2563
2564 /**
2565 * Init our video stream state variable */
2566 pC->VideoState = M4MCS_kStreamState_STARTED;
2567
2568 /**
2569 * Reset the stream reader */
2570 err = pC->m_pReader->m_pFctReset(pC->pReaderContext,
2571 (M4_StreamHandler *)pC->pReaderVideoStream);
2572
2573 if( M4NO_ERROR != err )
2574 {
2575 M4OSA_TRACE1_1(
2576 "M4MCS_open():\
2577 m_pReader->m_pFctReset(video) returns 0x%x",
2578 err);
2579 return err;
2580 }
2581
2582 /**
2583 * Initializes an access Unit */
2584 err = pC->m_pReader->m_pFctFillAuStruct(pC->pReaderContext,
2585 pStreamHandler, &pC->ReaderVideoAU);
2586
2587 if( M4NO_ERROR != err )
2588 {
2589 M4OSA_TRACE1_1(
2590 "M4MCS_open():\
2591 m_pReader->m_pFctFillAuStruct(video) returns 0x%x",
2592 err);
2593 return err;
2594 }
2595 }
2596 else /**< Not H263 or MPEG-4 (H264, etc.) */
2597 {
2598 M4OSA_TRACE1_1("M4MCS_open(): Found an unsupported video stream (0x%x) in\
2599 input 3gpp clip",
2600 pStreamHandler->m_streamType);
2601
2602 pC->bUnsupportedVideoFound = M4OSA_TRUE;
2603 pStreamHandler->m_bStreamIsOK = M4OSA_FALSE;
2604 }
2605 /* +CRLV6775 -H.264 Trimming */
2606 if( M4DA_StreamTypeVideoMpeg4Avc
2607 == pStreamHandler->m_streamType )
2608 {
2609
2610 // SPS and PPS are storead as per the 3gp file format
2611 pC->m_pInstance->m_pDecoderSpecificInfo =
2612 pStreamHandler->m_pH264DecoderSpecificInfo;
2613 pC->m_pInstance->m_decoderSpecificInfoSize =
2614 pStreamHandler->m_H264decoderSpecificInfoSize;
2615 }
2616 /* -CRLV6775 -H.264 Trimming */
2617 }
2618 /**
2619 * Found the first audio stream */
2620 else if( ( M4READER_kMediaFamilyAudio == mediaFamily)
2621 && (M4OSA_NULL == pC->pReaderAudioStream) )
2622 {
2623 if( ( M4DA_StreamTypeAudioAmrNarrowBand
2624 == pStreamHandler->m_streamType)
2625 || (M4DA_StreamTypeAudioAac == pStreamHandler->m_streamType)
2626 || (M4DA_StreamTypeAudioMp3
2627 == pStreamHandler->m_streamType)
2628 || (M4DA_StreamTypeAudioEvrc
2629 == pStreamHandler->m_streamType) )
2630 {
2631 M4OSA_TRACE3_0(
2632 "M4MCS_open(): Found an AMR-NB, AAC or MP3 audio stream in input clip");
2633
2634 /**
2635 * Keep pointer to the audio stream */
2636 pC->pReaderAudioStream =
2637 (M4_AudioStreamHandler *)pStreamHandler;
2638 pStreamHandler->m_bStreamIsOK = M4OSA_TRUE;
2639 pC->bUnsupportedAudioFound = M4OSA_FALSE;
2640
2641 /**
2642 * Init our audio stream state variable */
2643 pC->AudioState = M4MCS_kStreamState_STARTED;
2644
2645 /**
2646 * Reset the stream reader */
2647 err = pC->m_pReader->m_pFctReset(pC->pReaderContext,
2648 (M4_StreamHandler *)pC->pReaderAudioStream);
2649
2650 if( M4NO_ERROR != err )
2651 {
2652 M4OSA_TRACE1_1(
2653 "M4MCS_open():\
2654 m_pReader->m_pFctReset(audio) returns 0x%x",
2655 err);
2656 return err;
2657 }
2658
2659 /**
2660 * Initializes an access Unit */
2661 err = pC->m_pReader->m_pFctFillAuStruct(pC->pReaderContext,
2662 pStreamHandler, &pC->ReaderAudioAU);
2663
2664 if( M4NO_ERROR != err )
2665 {
2666 M4OSA_TRACE1_1(
2667 "M4MCS_open():\
2668 m_pReader->m_pFctFillAuStruct(audio) returns 0x%x",
2669 err);
2670 return err;
2671 }
2672
2673 /**
2674 * Output max AU size is equal to input max AU size (this value
2675 * will be changed if there is audio transcoding) */
2676 pC->uiAudioMaxAuSize = pStreamHandler->m_maxAUSize;
2677 }
2678 else
2679 {
2680 /**< Not AMR-NB, AAC, MP3 nor EVRC (AMR-WB, WAV...) */
2681 M4OSA_TRACE1_1("M4MCS_open(): Found an unsupported audio stream (0x%x) in \
2682 input 3gpp clip", pStreamHandler->m_streamType);
2683
2684 pC->bUnsupportedAudioFound = M4OSA_TRUE;
2685 pStreamHandler->m_bStreamIsOK = M4OSA_FALSE;
2686 }
2687 }
2688 }
2689 } /**< end of while (M4NO_ERROR == err) */
2690
2691 /**
2692 * Check we found at least one supported stream */
2693 if( ( M4OSA_NULL == pC->pReaderVideoStream)
2694 && (M4OSA_NULL == pC->pReaderAudioStream) )
2695 {
2696 M4OSA_TRACE1_0(
2697 "M4MCS_open(): returning M4MCS_ERR_INPUT_FILE_CONTAINS_NO_SUPPORTED_STREAM");
2698 return M4MCS_ERR_INPUT_FILE_CONTAINS_NO_SUPPORTED_STREAM;
2699 }
2700
2701 if( pC->VideoState == M4MCS_kStreamState_STARTED )
2702 {
2703 err = M4MCS_setCurrentVideoDecoder(pContext,
2704 pC->pReaderVideoStream->m_basicProperties.m_streamType);
2705 /*FB 2009-02-09: the error is check and returned only if video codecs are compiled,
2706 else only audio is used, that is why the editing process can continue*/
2707 #ifndef M4MCS_AUDIOONLY
2708
2709 M4ERR_CHECK_RETURN(err);
2710
2711 #else
2712
2713 if( ( M4NO_ERROR != err) && (M4MCS_WAR_MEDIATYPE_NOT_SUPPORTED != err) )
2714 {
2715 M4ERR_CHECK_RETURN(err);
2716 }
2717
2718 #endif /*M4MCS_AUDIOONLY*/
2719
2720 }
2721
2722 if( pC->AudioState == M4MCS_kStreamState_STARTED )
2723 {
2724 //EVRC
2725 if( M4DA_StreamTypeAudioEvrc
2726 != pStreamHandler->
2727 m_streamType ) /* decoder not supported yet, but allow to do null encoding */
2728 {
2729 err = M4MCS_setCurrentAudioDecoder(pContext,
2730 pC->pReaderAudioStream->m_basicProperties.m_streamType);
2731 M4ERR_CHECK_RETURN(err);
2732 }
2733 }
2734
2735 /**
2736 * Get the audio and video stream properties */
2737 err = M4MCS_intGetInputClipProperties(pC);
2738
2739 if( M4NO_ERROR != err )
2740 {
2741 M4OSA_TRACE1_1(
2742 "M4MCS_open(): M4MCS_intGetInputClipProperties returns 0x%x", err);
2743 return err;
2744 }
2745
2746 /**
2747 * Set the begin cut decoding increment according to the input frame rate */
2748 if( 0. != pC->InputFileProperties.fAverageFrameRate ) /**< sanity check */
2749 {
2750 pC->iVideoBeginDecIncr = (M4OSA_Int32)(3000.
2751 / pC->InputFileProperties.
2752 fAverageFrameRate); /**< about 3 frames */
2753 }
2754 else
2755 {
2756 pC->iVideoBeginDecIncr =
2757 200; /**< default value: 200 milliseconds (3 frames @ 15fps)*/
2758 }
2759
2760 /**
2761 * Update state automaton */
2762 pC->State = M4MCS_kState_OPENED;
2763
2764 /**
2765 * Return with no error */
2766 M4OSA_TRACE3_0("M4MCS_open(): returning M4NO_ERROR");
2767 return M4NO_ERROR;
2768 }
2769
2770 /**
2771 ******************************************************************************
2772 * M4OSA_ERR M4MCS_step(M4MCS_Context pContext, M4OSA_UInt8 *pProgress);
2773 * @brief Perform one step of trancoding.
2774 * @note
2775 * @param pContext (IN) MCS context
2776 * @param pProgress (OUT) Progress percentage (0 to 100) of the transcoding
2777 * @note pProgress must be a valid address.
2778 * @return M4NO_ERROR: No error
2779 * @return M4ERR_PARAMETER: One of the parameters is M4OSA_NULL (debug only)
2780 * @return M4ERR_STATE: MCS is not in an appropriate state for this function to be called
2781 * @return M4MCS_WAR_TRANSCODING_DONE: Transcoding is over, user should now call M4MCS_close()
2782 * @return M4MCS_ERR_AUDIO_CONVERSION_FAILED: The audio conversion (AAC to AMR-NB or MP3) failed
2783 * @return M4MCS_ERR_INVALID_AAC_SAMPLING_FREQUENCY: The input file contains an AAC audio track
2784 * with an invalid sampling frequency (should never happen)
2785 ******************************************************************************
2786 */
M4MCS_step(M4MCS_Context pContext,M4OSA_UInt8 * pProgress)2787 M4OSA_ERR M4MCS_step( M4MCS_Context pContext, M4OSA_UInt8 *pProgress )
2788 {
2789 M4MCS_InternalContext *pC = (M4MCS_InternalContext *)(pContext);
2790
2791 M4OSA_TRACE3_1("M4MCS_step called with pContext=0x%x", pContext);
2792
2793 /**
2794 * Check input parameters */
2795 M4OSA_DEBUG_IF2((M4OSA_NULL == pContext), M4ERR_PARAMETER,
2796 "M4MCS_step: pContext is M4OSA_NULL");
2797 M4OSA_DEBUG_IF2((M4OSA_NULL == pProgress), M4ERR_PARAMETER,
2798 "M4MCS_step: pProgress is M4OSA_NULL");
2799
2800 #ifdef M4MCS_SUPPORT_STILL_PICTURE
2801
2802 if( pC->m_bIsStillPicture )
2803 {
2804 /**
2805 * Call the still picture MCS functions*/
2806 return M4MCS_stillPicStep(pC, pProgress);
2807 }
2808
2809 #endif /*M4MCS_SUPPORT_STILL_PICTURE*/
2810
2811 /**
2812 * Check state automaton */
2813
2814 switch( pC->State )
2815 {
2816 case M4MCS_kState_READY:
2817 *pProgress = 0;
2818 return M4MCS_intStepSet(pC);
2819 break;
2820
2821 case M4MCS_kState_BEGINVIDEOJUMP:
2822 *pProgress = pC->uiProgress;
2823 return M4MCS_intStepBeginVideoJump(pC);
2824 break;
2825
2826 case M4MCS_kState_BEGINVIDEODECODE:
2827 *pProgress = pC->uiProgress;
2828 return M4MCS_intStepBeginVideoDecode(pC);
2829 break;
2830
2831 case M4MCS_kState_PROCESSING:
2832 {
2833 M4OSA_ERR err = M4NO_ERROR;
2834 err = M4MCS_intStepEncoding(pC, pProgress);
2835 /* Save progress info in case of pause */
2836 pC->uiProgress = *pProgress;
2837 return err;
2838 }
2839 break;
2840
2841 default: /**< State error */
2842 M4OSA_TRACE1_1(
2843 "M4MCS_step(): Wrong State (%d), returning M4ERR_STATE",
2844 pC->State);
2845 return M4ERR_STATE;
2846 }
2847 }
2848
2849 /**
2850 ******************************************************************************
2851 * M4OSA_ERR M4MCS_pause(M4MCS_Context pContext);
2852 * @brief Pause the transcoding i.e. release the (external hardware) video decoder.
2853 * @note This function is not needed if no hardware accelerators are used.
2854 * In that case, pausing the MCS is simply achieved by temporarily suspending
2855 * the M4MCS_step function calls.
2856 * @param pContext (IN) MCS context
2857 * @return M4NO_ERROR: No error
2858 * @return M4ERR_PARAMETER: pContext is M4OSA_NULL (debug only)
2859 * @return M4ERR_STATE: MCS is not in an appropriate state for this function to be called
2860 ******************************************************************************
2861 */
M4MCS_pause(M4MCS_Context pContext)2862 M4OSA_ERR M4MCS_pause( M4MCS_Context pContext )
2863 {
2864 M4MCS_InternalContext *pC = (M4MCS_InternalContext *)(pContext);
2865 M4OSA_ERR err;
2866
2867 M4OSA_TRACE2_1("M4MCS_pause called with pContext=0x%x", pContext);
2868
2869 /**
2870 * Check input parameters */
2871 M4OSA_DEBUG_IF2((M4OSA_NULL == pContext), M4ERR_PARAMETER,
2872 "M4MCS_pause: pContext is M4OSA_NULL");
2873
2874 #ifdef M4MCS_SUPPORT_STILL_PICTURE
2875
2876 if( pC->m_bIsStillPicture )
2877 {
2878 /**
2879 * Call the corresponding still picture MCS function*/
2880 return M4MCS_stillPicPause(pC);
2881 }
2882
2883 #endif /*M4MCS_SUPPORT_STILL_PICTURE*/
2884
2885 /**
2886 * Check state automaton */
2887
2888 switch( pC->State )
2889 {
2890 case M4MCS_kState_BEGINVIDEOJUMP: /**< the video decoder has been created,
2891 we must destroy it */
2892 case M4MCS_kState_BEGINVIDEODECODE: /**< the video is being used, we must destroy it */
2893 case M4MCS_kState_PROCESSING: /**< the video is being used, we must destroy it */
2894 /**< OK, nothing to do here */
2895 break;
2896
2897 default: /**< State error */
2898 M4OSA_TRACE1_1(
2899 "M4MCS_pause(): Wrong State (%d), returning M4ERR_STATE",
2900 pC->State);
2901 return M4ERR_STATE;
2902 }
2903
2904 /**
2905 * Set the CTS at which we will resume the decoding */
2906 if( pC->dViDecCurrentCts > pC->dViDecStartingCts )
2907 {
2908 /**
2909 * We passed the starting CTS, so the resume target is the current CTS */
2910 pC->dViDecStartingCts = pC->dViDecCurrentCts;
2911 }
2912 else {
2913 /**
2914 * We haven't passed the starting CTS yet, so the resume target is still the starting CTS
2915 * --> nothing to do in the else block */
2916 }
2917
2918 /**
2919 * Free video decoder stuff */
2920 if( M4OSA_NULL != pC->pViDecCtxt )
2921 {
2922 err = pC->m_pVideoDecoder->m_pFctDestroy(pC->pViDecCtxt);
2923 pC->pViDecCtxt = M4OSA_NULL;
2924
2925 if( M4NO_ERROR != err )
2926 {
2927 M4OSA_TRACE1_1(
2928 "M4MCS_pause: m_pVideoDecoder->pFctDestroy returns 0x%x", err);
2929 return err;
2930 }
2931 }
2932
2933 /**
2934 * State transition */
2935 pC->State = M4MCS_kState_PAUSED;
2936
2937 M4OSA_TRACE3_0("M4MCS_pause(): returning M4NO_ERROR");
2938 return M4NO_ERROR;
2939 }
2940
2941 /**
2942 ******************************************************************************
2943 * M4OSA_ERR M4MCS_resume(M4MCS_Context pContext);
2944 * @brief Resume the transcoding after a pause (see M4MCS_pause).
2945 * @note This function is not needed if no hardware accelerators are used.
2946 * In that case, resuming the MCS is simply achieved by calling
2947 * the M4MCS_step function.
2948 * @param pContext (IN) MCS context
2949 * @return M4NO_ERROR: No error
2950 * @return M4ERR_PARAMETER: pContext is M4OSA_NULL (debug only)
2951 * @return M4ERR_STATE: MCS is not in an appropriate state for this function to be called
2952 ******************************************************************************
2953 */
M4MCS_resume(M4MCS_Context pContext)2954 M4OSA_ERR M4MCS_resume( M4MCS_Context pContext )
2955 {
2956 M4MCS_InternalContext *pC = (M4MCS_InternalContext *)(pContext);
2957 M4OSA_ERR err;
2958
2959 M4OSA_TRACE2_1("M4MCS_resume called with pContext=0x%x", pContext);
2960
2961 /**
2962 * Check input parameters */
2963 M4OSA_DEBUG_IF2((M4OSA_NULL == pContext), M4ERR_PARAMETER,
2964 "M4MCS_resume: pContext is M4OSA_NULL");
2965
2966 #ifdef M4MCS_SUPPORT_STILL_PICTURE
2967
2968 if( pC->m_bIsStillPicture )
2969 {
2970 /**
2971 * Call the corresponding still picture MCS function*/
2972 return M4MCS_stillPicResume(pC);
2973 }
2974
2975 #endif /*M4MCS_SUPPORT_STILL_PICTURE*/
2976
2977 /**
2978 * Check state automaton */
2979
2980 switch( pC->State )
2981 {
2982 case M4MCS_kState_PAUSED: /**< OK, nothing to do here */
2983 break;
2984
2985 default: /**< State error */
2986 M4OSA_TRACE1_1(
2987 "M4MCS_resume(): Wrong State (%d), returning M4ERR_STATE",
2988 pC->State);
2989 return M4ERR_STATE;
2990 break;
2991 }
2992
2993 /**
2994 * Prepare the video decoder */
2995 err = M4MCS_intPrepareVideoDecoder(pC);
2996
2997 if( M4NO_ERROR != err )
2998 {
2999 M4OSA_TRACE1_1(
3000 "M4MCS_resume(): M4MCS_intPrepareVideoDecoder() returns 0x%x", err);
3001 return err;
3002 }
3003
3004 /**
3005 * State transition */
3006 if( 0.0 == pC->dViDecStartingCts )
3007 {
3008 /**
3009 * We are still at the beginning of the decoded stream, no need to jump, we can proceed */
3010 pC->State = M4MCS_kState_PROCESSING;
3011 }
3012 else
3013 {
3014 /**
3015 * Jumping */
3016 pC->State = M4MCS_kState_BEGINVIDEOJUMP;
3017 }
3018
3019 M4OSA_TRACE3_0("M4MCS_resume(): returning M4NO_ERROR");
3020 return M4NO_ERROR;
3021 }
3022
3023 /**
3024 ******************************************************************************
3025 * M4OSA_ERR M4MCS_close(M4MCS_Context pContext);
3026 * @brief Finish the MCS transcoding.
3027 * @note The output 3GPP file is ready to be played after this call
3028 * @param pContext (IN) MCS context
3029 * @return M4NO_ERROR: No error
3030 * @return M4ERR_PARAMETER: pContext is M4OSA_NULL (If Debug Level >= 2)
3031 * @return M4ERR_STATE: MCS is not in an appropriate state for this function to be called
3032 ******************************************************************************
3033 */
M4MCS_close(M4MCS_Context pContext)3034 M4OSA_ERR M4MCS_close( M4MCS_Context pContext )
3035 {
3036 M4MCS_InternalContext *pC = (M4MCS_InternalContext *)(pContext);
3037 M4ENCODER_Header *encHeader;
3038 M4SYS_StreamIDmemAddr streamHeader;
3039
3040 M4OSA_ERR err = M4NO_ERROR, err2;
3041
3042 M4OSA_TRACE2_1("M4MCS_close called with pContext=0x%x", pContext);
3043
3044 /**
3045 * Check input parameters */
3046 M4OSA_DEBUG_IF2((M4OSA_NULL == pContext), M4ERR_PARAMETER,
3047 "M4MCS_close: pContext is M4OSA_NULL");
3048
3049 #ifdef M4MCS_SUPPORT_STILL_PICTURE
3050
3051 if( pC->m_bIsStillPicture )
3052 {
3053 /**
3054 * Indicate that current file is no longer a still picture*/
3055 pC->m_bIsStillPicture = M4OSA_FALSE;
3056
3057 /**
3058 * Call the corresponding still picture MCS function*/
3059 return M4MCS_stillPicClose(pC);
3060 }
3061
3062 #endif /*M4MCS_SUPPORT_STILL_PICTURE*/
3063
3064 /**
3065 * Check state automaton */
3066
3067 if( M4MCS_kState_FINISHED != pC->State )
3068 {
3069 M4OSA_TRACE1_1("M4MCS_close(): Wrong State (%d), returning M4ERR_STATE",
3070 pC->State);
3071 return M4ERR_STATE;
3072 }
3073
3074 /* Close the encoder before the writer to be certain all the AUs have been written and we can
3075 get the DSI. */
3076
3077 /* Has the encoder actually been started? Don't stop it if that's not the case. */
3078 if( M4MCS_kEncoderRunning == pC->encoderState )
3079 {
3080 if( pC->pVideoEncoderGlobalFcts->pFctStop != M4OSA_NULL )
3081 {
3082 err = pC->pVideoEncoderGlobalFcts->pFctStop(pC->pViEncCtxt);
3083
3084 if( M4NO_ERROR != err )
3085 {
3086 M4OSA_TRACE1_1(
3087 "M4MCS_close: pVideoEncoderGlobalFcts->pFctStop returns 0x%x",
3088 err);
3089 /* Well... how the heck do you handle a failed cleanup? */
3090 }
3091 }
3092
3093 pC->encoderState = M4MCS_kEncoderStopped;
3094 }
3095
3096 /* Has the encoder actually been opened? Don't close it if that's not the case. */
3097 if( M4MCS_kEncoderStopped == pC->encoderState )
3098 {
3099 err = pC->pVideoEncoderGlobalFcts->pFctClose(pC->pViEncCtxt);
3100
3101 if( M4NO_ERROR != err )
3102 {
3103 M4OSA_TRACE1_1(
3104 "M4MCS_close: pVideoEncoderGlobalFcts->pFctClose returns 0x%x",
3105 err);
3106 /* Well... how the heck do you handle a failed cleanup? */
3107 }
3108
3109 pC->encoderState = M4MCS_kEncoderClosed;
3110 }
3111
3112 /**********************************/
3113 /******** Close the writer ********/
3114 /**********************************/
3115 if( M4OSA_NULL != pC->pWriterContext ) /* happens in state _SET */
3116 {
3117 /* HW encoder: fetch the DSI from the shell video encoder, and feed it to the writer before
3118 closing it. */
3119
3120 if( pC->novideo != M4OSA_TRUE )
3121 {
3122 if( ( M4ENCODER_kMPEG4 == pC->EncodingVideoFormat)
3123 || (M4ENCODER_kH264 == pC->EncodingVideoFormat) )
3124 {
3125 err = pC->pVideoEncoderGlobalFcts->pFctGetOption(pC->pViEncCtxt,
3126 M4ENCODER_kOptionID_EncoderHeader,
3127 (M4OSA_DataOption) &encHeader);
3128
3129 if( ( M4NO_ERROR != err) || (M4OSA_NULL == encHeader->pBuf) )
3130 {
3131 M4OSA_TRACE1_1(
3132 "M4MCS_close: failed to get the encoder header (err 0x%x)",
3133 err);
3134 /**< no return here, we still have stuff to deallocate after close, even
3135 if it fails. */
3136 }
3137 else
3138 {
3139 /* set this header in the writer */
3140 streamHeader.streamID = M4MCS_WRITER_VIDEO_STREAM_ID;
3141 streamHeader.size = encHeader->Size;
3142 streamHeader.addr = (M4OSA_MemAddr32)encHeader->pBuf;
3143 }
3144
3145 M4OSA_TRACE1_0("calling set option");
3146 err = pC->pWriterGlobalFcts->pFctSetOption(pC->pWriterContext,
3147 M4WRITER_kDSI, &streamHeader);
3148 M4OSA_TRACE1_0("set option done");
3149
3150 if( M4NO_ERROR != err )
3151 {
3152 M4OSA_TRACE1_1(
3153 "M4MCS_close: failed to set the DSI in the writer (err 0x%x)",
3154 err);
3155 }
3156 }
3157
3158 if( ( M4OSA_TRUE == pC->bH264Trim)
3159 && (M4ENCODER_kNULL == pC->EncodingVideoFormat) )
3160 {
3161 if(pC->uiBeginCutTime == 0)
3162 {
3163 M4OSA_TRACE1_1("Decoder specific info size = %d",
3164 pC->m_pInstance->m_decoderSpecificInfoSize);
3165 pC->m_pInstance->m_pFinalDSISize =
3166 pC->m_pInstance->m_decoderSpecificInfoSize;
3167 M4OSA_TRACE1_1("Decoder specific info pointer = %d",
3168 (M4OSA_MemAddr8)pC->m_pInstance->m_pDecoderSpecificInfo);
3169
3170 pC->m_pInstance->m_pFinalDSI =
3171 (M4OSA_UInt8 *)M4OSA_32bitAlignedMalloc(pC->m_pInstance-> \
3172 m_decoderSpecificInfoSize, M4MCS,
3173 (M4OSA_Char *)"instance->m_pFinalDSI");
3174
3175 if( pC->m_pInstance->m_pFinalDSI == M4OSA_NULL )
3176 {
3177 M4OSA_TRACE1_0("instance->m_pFinalDSI: allocation error");
3178 return M4ERR_ALLOC;
3179 }
3180 memcpy((void *)pC->m_pInstance->m_pFinalDSI,
3181 (void *)pC-> \
3182 m_pInstance->m_pDecoderSpecificInfo,
3183 pC->m_pInstance->m_decoderSpecificInfoSize);
3184 }
3185 streamHeader.streamID = M4MCS_WRITER_VIDEO_STREAM_ID;
3186 streamHeader.size = pC->m_pInstance->m_pFinalDSISize;
3187 streamHeader.addr =
3188 (M4OSA_MemAddr32)pC->m_pInstance->m_pFinalDSI;
3189 M4OSA_TRACE1_0("calling set option");
3190 err = pC->pWriterGlobalFcts->pFctSetOption(pC->pWriterContext,
3191 M4WRITER_kDSI, &streamHeader);
3192 M4OSA_TRACE1_0("set option done");
3193
3194 if( M4NO_ERROR != err )
3195 {
3196 M4OSA_TRACE1_1(
3197 "M4MCS_close: failed to set the DSI in the writer (err 0x%x)",
3198 err);
3199 }
3200 }
3201 }
3202 /* Write and close the 3GP output file */
3203 err2 = pC->pWriterGlobalFcts->pFctCloseWrite(pC->pWriterContext);
3204 pC->pWriterContext = M4OSA_NULL;
3205
3206 if( M4NO_ERROR != err2 )
3207 {
3208 M4OSA_TRACE1_1(
3209 "M4MCS_close: pWriterGlobalFcts->pFctCloseWrite returns 0x%x",
3210 err2);
3211
3212 if( M4NO_ERROR == err )
3213 err = err2;
3214 /**< no return here, we still have stuff to deallocate after close, even if it fails.*/
3215 }
3216 }
3217
3218 /* Close output PCM file if needed */
3219 if( pC->pOutputPCMfile != M4OSA_NULL )
3220 {
3221 pC->pOsaFileWritPtr->closeWrite(pC->pOutputPCMfile);
3222 pC->pOutputPCMfile = M4OSA_NULL;
3223 }
3224
3225 /*FlB 2009.03.04: add audio effects,
3226 free effects list*/
3227 if( M4OSA_NULL != pC->pEffects )
3228 {
3229 free(pC->pEffects);
3230 pC->pEffects = M4OSA_NULL;
3231 }
3232 pC->nbEffects = 0;
3233 pC->pActiveEffectNumber = -1;
3234
3235 /**
3236 * State transition */
3237 pC->State = M4MCS_kState_CLOSED;
3238
3239 if( M4OSA_NULL != pC->H264MCSTempBuffer )
3240 {
3241 free(pC->H264MCSTempBuffer);
3242 }
3243
3244 M4OSA_TRACE3_0("M4MCS_close(): returning M4NO_ERROR");
3245 return err;
3246 }
3247
3248 /**
3249 ******************************************************************************
3250 * M4OSA_ERR M4MCS_cleanUp(M4MCS_Context pContext);
3251 * @brief Free all resources used by the MCS.
3252 * @note The context is no more valid after this call
3253 * @param pContext (IN) MCS context
3254 * @return M4NO_ERROR: No error
3255 * @return M4ERR_PARAMETER: pContext is M4OSA_NULL (If Debug Level >= 2)
3256 * @return M4ERR_STATE: MCS is not in an appropriate state for this function to be called
3257 ******************************************************************************
3258 */
M4MCS_cleanUp(M4MCS_Context pContext)3259 M4OSA_ERR M4MCS_cleanUp( M4MCS_Context pContext )
3260 {
3261 M4OSA_ERR err = M4NO_ERROR;
3262 M4MCS_InternalContext *pC = (M4MCS_InternalContext *)(pContext);
3263
3264 M4OSA_TRACE3_1("M4MCS_cleanUp called with pContext=0x%x", pContext);
3265
3266 #ifdef MCS_DUMP_PCM_TO_FILE
3267
3268 if( file_au_reader )
3269 {
3270 fclose(file_au_reader);
3271 file_au_reader = NULL;
3272 }
3273
3274 if( file_pcm_decoder )
3275 {
3276 fclose(file_pcm_decoder);
3277 file_pcm_decoder = NULL;
3278 }
3279
3280 if( file_pcm_encoder )
3281 {
3282 fclose(file_pcm_encoder);
3283 file_pcm_encoder = NULL;
3284 }
3285
3286 #endif
3287
3288 /**
3289 * Check input parameter */
3290
3291 if( M4OSA_NULL == pContext )
3292 {
3293 M4OSA_TRACE1_0(
3294 "M4MCS_cleanUp: pContext is M4OSA_NULL, returning M4ERR_PARAMETER");
3295 return M4ERR_PARAMETER;
3296 }
3297
3298 /**
3299 * Check state automaton */
3300 if( M4MCS_kState_CLOSED != pC->State )
3301 {
3302 M4OSA_TRACE1_1(
3303 "M4MCS_cleanUp(): Wrong State (%d), returning M4ERR_STATE",
3304 pC->State);
3305 return M4ERR_STATE;
3306 }
3307
3308 if( M4OSA_NULL != pC->m_pInstance )
3309 {
3310 err = H264MCS_Freeinstance(pC->m_pInstance);
3311 pC->m_pInstance = M4OSA_NULL;
3312 }
3313
3314 /* ----- Free video encoder stuff, if needed ----- */
3315
3316 if( ( M4OSA_NULL != pC->pViEncCtxt)
3317 && (M4OSA_NULL != pC->pVideoEncoderGlobalFcts) )
3318 {
3319 err = pC->pVideoEncoderGlobalFcts->pFctCleanup(pC->pViEncCtxt);
3320 pC->pViEncCtxt = M4OSA_NULL;
3321
3322 if( M4NO_ERROR != err )
3323 {
3324 M4OSA_TRACE1_1(
3325 "M4MCS_cleanUp: pVideoEncoderGlobalFcts->pFctCleanup returns 0x%x",
3326 err);
3327 /**< don't return, we still have stuff to free */
3328 }
3329
3330 pC->encoderState = M4MCS_kNoEncoder;
3331 }
3332
3333 /**
3334 * In the H263 case, we allocated our own DSI buffer */
3335 if( ( M4ENCODER_kH263 == pC->EncodingVideoFormat)
3336 && (M4OSA_NULL != pC->WriterVideoStreamInfo.Header.pBuf) )
3337 {
3338 free(pC->WriterVideoStreamInfo.Header.pBuf);
3339 pC->WriterVideoStreamInfo.Header.pBuf = M4OSA_NULL;
3340 }
3341
3342 if( M4OSA_NULL != pC->pPreResizeFrame )
3343 {
3344 if( M4OSA_NULL != pC->pPreResizeFrame[0].pac_data )
3345 {
3346 free(pC->pPreResizeFrame[0].pac_data);
3347 pC->pPreResizeFrame[0].pac_data = M4OSA_NULL;
3348 }
3349
3350 if( M4OSA_NULL != pC->pPreResizeFrame[1].pac_data )
3351 {
3352 free(pC->pPreResizeFrame[1].pac_data);
3353 pC->pPreResizeFrame[1].pac_data = M4OSA_NULL;
3354 }
3355
3356 if( M4OSA_NULL != pC->pPreResizeFrame[2].pac_data )
3357 {
3358 free(pC->pPreResizeFrame[2].pac_data);
3359 pC->pPreResizeFrame[2].pac_data = M4OSA_NULL;
3360 }
3361 free(pC->pPreResizeFrame);
3362 pC->pPreResizeFrame = M4OSA_NULL;
3363 }
3364
3365 /* ----- Free the ssrc stuff ----- */
3366
3367 if( M4OSA_NULL != pC->SsrcScratch )
3368 {
3369 free(pC->SsrcScratch);
3370 pC->SsrcScratch = M4OSA_NULL;
3371 }
3372
3373 if( M4OSA_NULL != pC->pSsrcBufferIn )
3374 {
3375 free(pC->pSsrcBufferIn);
3376 pC->pSsrcBufferIn = M4OSA_NULL;
3377 }
3378
3379 if( M4OSA_NULL != pC->pSsrcBufferOut )
3380 {
3381 free(pC->pSsrcBufferOut);
3382 pC->pSsrcBufferOut = M4OSA_NULL;
3383 }
3384
3385 if (pC->pLVAudioResampler != M4OSA_NULL)
3386 {
3387 LVDestroy(pC->pLVAudioResampler);
3388 pC->pLVAudioResampler = M4OSA_NULL;
3389 }
3390
3391 /* ----- Free the audio encoder stuff ----- */
3392
3393 if( M4OSA_NULL != pC->pAudioEncCtxt )
3394 {
3395 err = pC->pAudioEncoderGlobalFcts->pFctClose(pC->pAudioEncCtxt);
3396
3397 if( M4NO_ERROR != err )
3398 {
3399 M4OSA_TRACE1_1(
3400 "M4MCS_cleanUp: pAudioEncoderGlobalFcts->pFctClose returns 0x%x",
3401 err);
3402 /**< don't return, we still have stuff to free */
3403 }
3404
3405 err = pC->pAudioEncoderGlobalFcts->pFctCleanUp(pC->pAudioEncCtxt);
3406
3407 if( M4NO_ERROR != err )
3408 {
3409 M4OSA_TRACE1_1(
3410 "M4MCS_cleanUp: pAudioEncoderGlobalFcts->pFctCleanUp returns 0x%x",
3411 err);
3412 /**< don't return, we still have stuff to free */
3413 }
3414
3415 pC->pAudioEncCtxt = M4OSA_NULL;
3416 }
3417
3418 if( M4OSA_NULL != pC->pAudioEncoderBuffer )
3419 {
3420 free(pC->pAudioEncoderBuffer);
3421 pC->pAudioEncoderBuffer = M4OSA_NULL;
3422 }
3423
3424 /* ----- Free all other stuff ----- */
3425
3426 /**
3427 * Free the readers and the decoders */
3428 M4MCS_intCleanUp_ReadersDecoders(pC);
3429
3430 #ifdef M4MCS_SUPPORT_STILL_PICTURE
3431 /**
3432 * Free the still picture resources */
3433
3434 M4MCS_stillPicCleanUp(pC);
3435
3436 #endif /*M4MCS_SUPPORT_STILL_PICTURE*/
3437
3438 /**
3439 * Free the shells interfaces */
3440
3441 M4MCS_unRegisterAllWriters(pContext);
3442 M4MCS_unRegisterAllEncoders(pContext);
3443 M4MCS_unRegisterAllReaders(pContext);
3444 M4MCS_unRegisterAllDecoders(pContext);
3445
3446 /**
3447 * Free the context itself */
3448 free(pC);
3449 pC = M4OSA_NULL;
3450
3451 M4OSA_TRACE3_0("M4MCS_cleanUp(): returning M4NO_ERROR");
3452 return M4NO_ERROR;
3453 }
3454
3455 /**
3456 ******************************************************************************
3457 * M4OSA_ERR M4MCS_abort(M4MCS_Context pContext);
3458 * @brief Finish the MCS transcoding and free all resources used by the MCS
3459 * whatever the state is.
3460 * @note The context is no more valid after this call
3461 * @param pContext (IN) MCS context
3462 * @return M4NO_ERROR: No error
3463 * @return M4ERR_PARAMETER: pContext is M4OSA_NULL (debug only)
3464 ******************************************************************************
3465 */
M4MCS_abort(M4MCS_Context pContext)3466 M4OSA_ERR M4MCS_abort( M4MCS_Context pContext )
3467 {
3468 M4OSA_ERR err = M4NO_ERROR;
3469 M4OSA_ERR err1 = M4NO_ERROR;
3470 M4MCS_InternalContext *pC = (M4MCS_InternalContext *)(pContext);
3471
3472 if( M4OSA_NULL == pContext )
3473 {
3474 return M4NO_ERROR;
3475 }
3476
3477 if( ( pC->State == M4MCS_kState_CREATED)
3478 || (pC->State == M4MCS_kState_CLOSED) )
3479 {
3480 pC->State = M4MCS_kState_CLOSED;
3481
3482 err = M4MCS_cleanUp(pContext);
3483
3484 if( err != M4NO_ERROR )
3485 {
3486 M4OSA_TRACE1_1("M4MCS_abort : M4MCS_cleanUp fails err = 0x%x", err);
3487 }
3488 }
3489 else
3490 {
3491 #ifdef M4MCS_SUPPORT_STILL_PICTURE
3492
3493 if( pC->m_bIsStillPicture )
3494 {
3495 /**
3496 * Cancel the ongoing processes if any*/
3497 err = M4MCS_stillPicCancel(pC);
3498
3499 if( err != M4NO_ERROR )
3500 {
3501 M4OSA_TRACE1_1(
3502 "M4MCS_abort : M4MCS_stillPicCancel fails err = 0x%x", err);
3503 }
3504 /*Still picture process is now stopped; Carry on with close and cleanup*/
3505 }
3506
3507 #endif /*M4MCS_SUPPORT_STILL_PICTURE*/
3508
3509 pC->State = M4MCS_kState_FINISHED;
3510
3511 err = M4MCS_close(pContext);
3512
3513 if( err != M4NO_ERROR )
3514 {
3515 M4OSA_TRACE1_1("M4MCS_abort : M4MCS_close fails err = 0x%x", err);
3516 err1 = err;
3517 }
3518
3519 err = M4MCS_cleanUp(pContext);
3520
3521 if( err != M4NO_ERROR )
3522 {
3523 M4OSA_TRACE1_1("M4MCS_abort : M4MCS_cleanUp fails err = 0x%x", err);
3524 }
3525 }
3526 err = (err1 == M4NO_ERROR) ? err : err1;
3527 return err;
3528 }
3529
3530 /**
3531 ******************************************************************************
3532 * M4OSA_ERR M4MCS_getInputFileProperties(M4MCS_Context pContext,
3533 * M4VIDEOEDITING_ClipProperties* pFileProperties);
3534 * @brief Retrieves the properties of the audio and video streams from the input file.
3535 * @param pContext (IN) MCS context
3536 * @param pProperties (OUT) Pointer on an allocated M4VIDEOEDITING_ClipProperties
3537 structure which is filled with the input stream properties.
3538 * @note The structure pProperties must be allocated and further de-allocated
3539 by the application. The function must be called in the opened state.
3540 * @return M4NO_ERROR: No error
3541 * @return M4ERR_PARAMETER: At least one parameter is M4OSA_NULL
3542 * @return M4ERR_STATE: MCS is not in an appropriate state for this function to be called
3543 ******************************************************************************
3544 */
M4MCS_getInputFileProperties(M4MCS_Context pContext,M4VIDEOEDITING_ClipProperties * pFileProperties)3545 M4OSA_ERR M4MCS_getInputFileProperties( M4MCS_Context pContext,
3546 M4VIDEOEDITING_ClipProperties *pFileProperties )
3547 {
3548 M4MCS_InternalContext *pC = (M4MCS_InternalContext *)(pContext);
3549
3550 M4OSA_TRACE2_2("M4MCS_getInputFileProperties called with pContext=0x%x, \
3551 pFileProperties=0x%x", pContext, pFileProperties);
3552
3553 /**
3554 * Check input parameters */
3555 M4OSA_DEBUG_IF2((M4OSA_NULL == pContext), M4ERR_PARAMETER,
3556 "M4MCS_getInputFileProperties: pContext is M4OSA_NULL");
3557 M4OSA_DEBUG_IF2((M4OSA_NULL == pFileProperties), M4ERR_PARAMETER,
3558 "M4MCS_getInputFileProperties: pProperties is M4OSA_NULL");
3559
3560 #ifdef M4MCS_SUPPORT_STILL_PICTURE
3561
3562 if( pC->m_bIsStillPicture )
3563 {
3564 /**
3565 * Call the corresponding still picture MCS function*/
3566 return M4MCS_stillPicGetInputFileProperties(pC, pFileProperties);
3567 }
3568
3569 #endif /*M4MCS_SUPPORT_STILL_PICTURE*/
3570
3571 /**
3572 * Check state automaton */
3573
3574 if( M4MCS_kState_OPENED != pC->State )
3575 {
3576 M4OSA_TRACE1_1(
3577 "M4MCS_getInputFileProperties(): Wrong State (%d), returning M4ERR_STATE",
3578 pC->State);
3579 return M4ERR_STATE;
3580 }
3581
3582 /**
3583 * Copy previously computed properties into given structure */
3584 memcpy((void *)pFileProperties,
3585 (void *) &pC->InputFileProperties,
3586 sizeof(M4VIDEOEDITING_ClipProperties));
3587
3588 return M4NO_ERROR;
3589 }
3590
3591 /**
3592 ******************************************************************************
3593 * M4OSA_ERR M4MCS_setOutputParams(M4MCS_Context pContext, M4MCS_OutputParams* pParams);
3594 * @brief Set the MCS video output parameters.
3595 * @note Must be called after M4MCS_open. Must be called before M4MCS_step.
3596 * @param pContext (IN) MCS context
3597 * @param pParams (IN/OUT) Transcoding parameters
3598 * @return M4NO_ERROR: No error
3599 * @return M4ERR_PARAMETER: At least one parameter is M4OSA_NULL (debug only)
3600 * @return M4ERR_STATE: MCS is not in an appropriate state for this function to be called
3601 * @return M4MCS_ERR_INVALID_VIDEO_FRAME_SIZE_FOR_H263 : Output video frame size parameter is
3602 * incompatible with H263 encoding
3603 * @return M4MCS_ERR_INVALID_VIDEO_FRAME_RATE_FOR_H263 : Output video frame size parameter is
3604 * incompatible with H263 encoding
3605 * @return M4MCS_ERR_UNDEFINED_OUTPUT_VIDEO_FORMAT : Undefined output video format parameter
3606 * @return M4MCS_ERR_UNDEFINED_OUTPUT_VIDEO_FRAME_SIZE : Undefined output video frame size
3607 * @return M4MCS_ERR_UNDEFINED_OUTPUT_VIDEO_FRAME_RATE : Undefined output video frame rate
3608 * @return M4MCS_ERR_UNDEFINED_OUTPUT_AUDIO_FORMAT : Undefined output audio format parameter
3609 * @return M4MCS_ERR_DURATION_IS_NULL : Specified output parameters define a null duration stream
3610 * (no audio and video)
3611 ******************************************************************************
3612 */
M4MCS_setOutputParams(M4MCS_Context pContext,M4MCS_OutputParams * pParams)3613 M4OSA_ERR M4MCS_setOutputParams( M4MCS_Context pContext,
3614 M4MCS_OutputParams *pParams )
3615 {
3616 M4MCS_InternalContext *pC = (M4MCS_InternalContext *)(pContext);
3617 M4OSA_UInt32 uiFrameWidth;
3618 M4OSA_UInt32 uiFrameHeight;
3619 M4OSA_ERR err;
3620
3621 M4OSA_TRACE2_2(
3622 "M4MCS_setOutputParams called with pContext=0x%x, pParams=0x%x",
3623 pContext, pParams);
3624
3625 /**
3626 * Check input parameters */
3627 M4OSA_DEBUG_IF2((M4OSA_NULL == pContext), M4ERR_PARAMETER,
3628 "M4MCS_setOutputParams: pContext is M4OSA_NULL");
3629 M4OSA_DEBUG_IF2((M4OSA_NULL == pParams), M4ERR_PARAMETER,
3630 "M4MCS_setOutputParams: pParam is M4OSA_NULL");
3631
3632 #ifdef M4MCS_SUPPORT_STILL_PICTURE
3633
3634 if( pC->m_bIsStillPicture )
3635 {
3636 /**
3637 * Call the corresponding still picture MCS function*/
3638 return M4MCS_stillPicSetOutputParams(pC, pParams);
3639 }
3640
3641 #endif /*M4MCS_SUPPORT_STILL_PICTURE*/
3642
3643 /**
3644 * Check state automaton */
3645
3646 if( M4MCS_kState_OPENED != pC->State )
3647 {
3648 M4OSA_TRACE1_1(
3649 "M4MCS_setOutputParams(): Wrong State (%d), returning M4ERR_STATE",
3650 pC->State);
3651 return M4ERR_STATE;
3652 }
3653
3654 /* Ignore audio or video stream if the output do not need it, */
3655 /* or if the input file does not have any audio or video stream */
3656 /*FlB 26.02.2009: add mp3 as mcs output format*/
3657 if( ( pParams->OutputVideoFormat == M4VIDEOEDITING_kNoneVideo)
3658 || (pC->VideoState == M4MCS_kStreamState_NOSTREAM)
3659 || (pParams->OutputFileType == M4VIDEOEDITING_kFileType_AMR)
3660 || (pParams->OutputFileType == M4VIDEOEDITING_kFileType_MP3) )
3661 {
3662 pC->novideo = M4OSA_TRUE;
3663 }
3664
3665 if( ( pParams->OutputAudioFormat == M4VIDEOEDITING_kNoneAudio)
3666 || (pC->AudioState == M4MCS_kStreamState_NOSTREAM) )
3667 {
3668 pC->noaudio = M4OSA_TRUE;
3669 }
3670
3671 if( pC->noaudio && pC->novideo )
3672 {
3673 M4OSA_TRACE1_0(
3674 "!!! M4MCS_setOutputParams : clip is NULL, there is no audio, no video");
3675 return M4MCS_ERR_DURATION_IS_NULL;
3676 }
3677
3678 /* Set writer */
3679 err = M4MCS_setCurrentWriter(pContext, pParams->OutputFileType);
3680 M4ERR_CHECK_RETURN(err);
3681
3682 /* Set video parameters */
3683 if( pC->novideo == M4OSA_FALSE )
3684 {
3685 /**
3686 * Check Video Format correctness */
3687
3688 switch( pParams->OutputVideoFormat )
3689 {
3690 case M4VIDEOEDITING_kH263:
3691 if( pParams->OutputFileType == M4VIDEOEDITING_kFileType_MP4 )
3692 return M4MCS_ERR_H263_FORBIDDEN_IN_MP4_FILE;
3693
3694 pC->EncodingVideoFormat = M4ENCODER_kH263;
3695 err = M4MCS_setCurrentVideoEncoder(pContext,
3696 pParams->OutputVideoFormat);
3697 M4ERR_CHECK_RETURN(err);
3698 break;
3699
3700 case M4VIDEOEDITING_kMPEG4:
3701
3702 pC->EncodingVideoFormat = M4ENCODER_kMPEG4;
3703 err = M4MCS_setCurrentVideoEncoder(pContext,
3704 pParams->OutputVideoFormat);
3705 M4ERR_CHECK_RETURN(err);
3706 break;
3707
3708 case M4VIDEOEDITING_kH264:
3709
3710 pC->EncodingVideoFormat = M4ENCODER_kH264;
3711 err = M4MCS_setCurrentVideoEncoder(pContext,
3712 pParams->OutputVideoFormat);
3713 M4ERR_CHECK_RETURN(err);
3714 break;
3715
3716 case M4VIDEOEDITING_kNullVideo:
3717 if( ( pParams->OutputFileType == M4VIDEOEDITING_kFileType_MP4)
3718 && (pC->InputFileProperties.VideoStreamType
3719 == M4VIDEOEDITING_kH263) )
3720 return M4MCS_ERR_H263_FORBIDDEN_IN_MP4_FILE;
3721
3722
3723 /* Encoder needed for begin cut to generate an I-frame */
3724 pC->EncodingVideoFormat = M4ENCODER_kNULL;
3725 err = M4MCS_setCurrentVideoEncoder(pContext,
3726 pC->InputFileProperties.VideoStreamType);
3727 M4ERR_CHECK_RETURN(err);
3728 break;
3729
3730 default:
3731 M4OSA_TRACE1_1("M4MCS_setOutputParams: Undefined output video format (%d),\
3732 returning M4MCS_ERR_UNDEFINED_OUTPUT_VIDEO_FORMAT",
3733 pParams->OutputVideoFormat);
3734 return M4MCS_ERR_UNDEFINED_OUTPUT_VIDEO_FORMAT;
3735 }
3736
3737 /**
3738 * Check Video frame size correctness */
3739 if( M4VIDEOEDITING_kNullVideo == pParams->OutputVideoFormat )
3740 {
3741 uiFrameWidth =
3742 pC->EncodingWidth = pC->InputFileProperties.uiVideoWidth;
3743 uiFrameHeight =
3744 pC->EncodingHeight = pC->InputFileProperties.uiVideoHeight;
3745
3746 /**
3747 * Set output video profile and level */
3748 pC->encodingVideoProfile = pC->InputFileProperties.uiVideoProfile;
3749 pC->encodingVideoLevel = pC->InputFileProperties.uiVideoLevel;
3750
3751 // Clip's original width and height may not be
3752 // multiple of 16.
3753 // Ensure encoding width and height are multiple of 16
3754
3755 uint32_t remainder = pC->EncodingWidth % 16;
3756 if (remainder != 0) {
3757 if (remainder >= 8) {
3758 // Roll forward
3759 pC->EncodingWidth =
3760 pC->EncodingWidth + (16-remainder);
3761 } else {
3762 // Roll backward
3763 pC->EncodingWidth =
3764 pC->EncodingWidth - remainder;
3765 }
3766 uiFrameWidth = pC->EncodingWidth;
3767 }
3768
3769 remainder = pC->EncodingHeight % 16;
3770 if (remainder != 0) {
3771 if (remainder >= 8) {
3772 // Roll forward
3773 pC->EncodingHeight =
3774 pC->EncodingHeight + (16-remainder);
3775 } else {
3776 // Roll backward
3777 pC->EncodingHeight =
3778 pC->EncodingHeight - remainder;
3779 }
3780 uiFrameHeight = pC->EncodingHeight;
3781 }
3782
3783 }
3784 else
3785 {
3786 /**
3787 * Set output video profile and level */
3788 pC->encodingVideoProfile = pParams->outputVideoProfile;
3789 pC->encodingVideoLevel = pParams->outputVideoLevel;
3790
3791 switch( pParams->OutputVideoFrameSize )
3792 {
3793 case M4VIDEOEDITING_kSQCIF:
3794 uiFrameWidth = pC->EncodingWidth = M4ENCODER_SQCIF_Width;
3795 uiFrameHeight = pC->EncodingHeight = M4ENCODER_SQCIF_Height;
3796 break;
3797
3798 case M4VIDEOEDITING_kQQVGA:
3799 uiFrameWidth = pC->EncodingWidth = M4ENCODER_QQVGA_Width;
3800 uiFrameHeight = pC->EncodingHeight = M4ENCODER_QQVGA_Height;
3801 break;
3802
3803 case M4VIDEOEDITING_kQCIF:
3804 uiFrameWidth = pC->EncodingWidth = M4ENCODER_QCIF_Width;
3805 uiFrameHeight = pC->EncodingHeight = M4ENCODER_QCIF_Height;
3806 break;
3807
3808 case M4VIDEOEDITING_kQVGA:
3809 uiFrameWidth = pC->EncodingWidth = M4ENCODER_QVGA_Width;
3810 uiFrameHeight = pC->EncodingHeight = M4ENCODER_QVGA_Height;
3811 break;
3812
3813 case M4VIDEOEDITING_kCIF:
3814 uiFrameWidth = pC->EncodingWidth = M4ENCODER_CIF_Width;
3815 uiFrameHeight = pC->EncodingHeight = M4ENCODER_CIF_Height;
3816 break;
3817
3818 case M4VIDEOEDITING_kVGA:
3819 uiFrameWidth = pC->EncodingWidth = M4ENCODER_VGA_Width;
3820 uiFrameHeight = pC->EncodingHeight = M4ENCODER_VGA_Height;
3821 break;
3822 /* +PR LV5807 */
3823 case M4VIDEOEDITING_kWVGA:
3824 uiFrameWidth = pC->EncodingWidth = M4ENCODER_WVGA_Width;
3825 uiFrameHeight = pC->EncodingHeight = M4ENCODER_WVGA_Height;
3826 break;
3827
3828 case M4VIDEOEDITING_kNTSC:
3829 uiFrameWidth = pC->EncodingWidth = M4ENCODER_NTSC_Width;
3830 uiFrameHeight = pC->EncodingHeight = M4ENCODER_NTSC_Height;
3831 break;
3832 /* -PR LV5807*/
3833 /* +CR Google */
3834 case M4VIDEOEDITING_k640_360:
3835 uiFrameWidth = pC->EncodingWidth = M4ENCODER_640_360_Width;
3836 uiFrameHeight =
3837 pC->EncodingHeight = M4ENCODER_640_360_Height;
3838 break;
3839
3840 case M4VIDEOEDITING_k854_480:
3841 uiFrameWidth =
3842 pC->EncodingWidth = M4ENCODER_854_480_Width;
3843 uiFrameHeight =
3844 pC->EncodingHeight = M4ENCODER_854_480_Height;
3845 break;
3846
3847 case M4VIDEOEDITING_k1280_720:
3848 uiFrameWidth =
3849 pC->EncodingWidth = M4ENCODER_1280_720_Width;
3850 uiFrameHeight =
3851 pC->EncodingHeight = M4ENCODER_1280_720_Height;
3852 break;
3853
3854 case M4VIDEOEDITING_k1080_720:
3855 uiFrameWidth =
3856 pC->EncodingWidth = M4ENCODER_1080_720_Width;
3857 uiFrameHeight =
3858 pC->EncodingHeight = M4ENCODER_1080_720_Height;
3859 break;
3860
3861 case M4VIDEOEDITING_k960_720:
3862 uiFrameWidth =
3863 pC->EncodingWidth = M4ENCODER_960_720_Width;
3864 uiFrameHeight =
3865 pC->EncodingHeight = M4ENCODER_960_720_Height;
3866 break;
3867
3868 case M4VIDEOEDITING_k1920_1080:
3869 uiFrameWidth =
3870 pC->EncodingWidth = M4ENCODER_1920_1080_Width;
3871 uiFrameHeight =
3872 pC->EncodingHeight = M4ENCODER_1920_1080_Height;
3873 break;
3874 /* -CR Google */
3875 default:
3876 M4OSA_TRACE1_1(
3877 "M4MCS_setOutputParams: Undefined output video frame size \
3878 (%d), returning M4MCS_ERR_UNDEFINED_OUTPUT_VIDEO_FRAME_SIZE",
3879 pParams->OutputVideoFrameSize);
3880 return M4MCS_ERR_UNDEFINED_OUTPUT_VIDEO_FRAME_SIZE;
3881 }
3882 }
3883
3884 /**
3885 * Compute video max au size and max chunck size.
3886 * We do it here because it depends on the frame size only, and
3887 * because we need it for the file size/video bitrate estimations */
3888 pC->uiVideoMaxAuSize =
3889 (M4OSA_UInt32)(1.5F *(M4OSA_Float)(uiFrameWidth * uiFrameHeight) \
3890 *M4MCS_VIDEO_MIN_COMPRESSION_RATIO);
3891 pC->uiVideoMaxChunckSize = (M4OSA_UInt32)(pC->uiVideoMaxAuSize \
3892 *
3893 M4MCS_VIDEO_CHUNK_AU_SIZE_RATIO); /**< from max AU size to max Chunck size */
3894
3895 if( 0 == pC->uiVideoMaxAuSize )
3896 {
3897 /* Size may be zero in case of null encoding with unrecognized stream */
3898 M4OSA_TRACE1_0("M4MCS_setOutputParams: video frame size is 0 returning\
3899 M4MCS_ERR_UNDEFINED_OUTPUT_VIDEO_FRAME_SIZE");
3900 return M4MCS_ERR_UNDEFINED_OUTPUT_VIDEO_FRAME_SIZE;
3901 }
3902
3903
3904 /**
3905 * Size check for H263 (only valid sizes are CIF, QCIF and SQCIF) */
3906
3907 if( M4VIDEOEDITING_kH263 == pParams->OutputVideoFormat )
3908 {
3909 switch( pParams->OutputVideoFrameSize )
3910 {
3911 case M4VIDEOEDITING_kSQCIF:
3912 case M4VIDEOEDITING_kQCIF:
3913 case M4VIDEOEDITING_kCIF:
3914 /* OK */
3915 break;
3916
3917 default:
3918 M4OSA_TRACE1_0(
3919 "M4MCS_setOutputParams():\
3920 returning M4MCS_ERR_INVALID_VIDEO_FRAME_SIZE_FOR_H263");
3921 return M4MCS_ERR_INVALID_VIDEO_FRAME_SIZE_FOR_H263;
3922 }
3923 }
3924
3925 /**
3926 * Check Video Frame rate correctness */
3927 if( M4VIDEOEDITING_kNullVideo != pParams->OutputVideoFormat )
3928 {
3929 switch( pParams->OutputVideoFrameRate )
3930 {
3931 case M4VIDEOEDITING_k5_FPS:
3932 pC->EncodingVideoFramerate = M4ENCODER_k5_FPS;
3933 break;
3934
3935 case M4VIDEOEDITING_k7_5_FPS:
3936 pC->EncodingVideoFramerate = M4ENCODER_k7_5_FPS;
3937 break;
3938
3939 case M4VIDEOEDITING_k10_FPS:
3940 pC->EncodingVideoFramerate = M4ENCODER_k10_FPS;
3941 break;
3942
3943 case M4VIDEOEDITING_k12_5_FPS:
3944 pC->EncodingVideoFramerate = M4ENCODER_k12_5_FPS;
3945 break;
3946
3947 case M4VIDEOEDITING_k15_FPS:
3948 pC->EncodingVideoFramerate = M4ENCODER_k15_FPS;
3949 break;
3950
3951 case M4VIDEOEDITING_k20_FPS:
3952 pC->EncodingVideoFramerate = M4ENCODER_k20_FPS;
3953 break;
3954
3955 case M4VIDEOEDITING_k25_FPS:
3956 pC->EncodingVideoFramerate = M4ENCODER_k25_FPS;
3957 break;
3958
3959 case M4VIDEOEDITING_k30_FPS:
3960 pC->EncodingVideoFramerate = M4ENCODER_k30_FPS;
3961 break;
3962
3963 default:
3964 M4OSA_TRACE1_1(
3965 "M4MCS_setOutputParams: Undefined output video frame rate\
3966 (%d), returning M4MCS_ERR_UNDEFINED_OUTPUT_VIDEO_FRAME_RATE",
3967 pParams->OutputVideoFrameRate);
3968 return M4MCS_ERR_UNDEFINED_OUTPUT_VIDEO_FRAME_RATE;
3969 }
3970 }
3971
3972 /**
3973 * Frame rate check for H263 (only dividers of 30 fps (29.97 actually)) */
3974 if( M4VIDEOEDITING_kH263 == pParams->OutputVideoFormat )
3975 {
3976 switch( pC->EncodingVideoFramerate )
3977 {
3978 case M4ENCODER_k5_FPS:
3979 case M4ENCODER_k7_5_FPS:
3980 case M4ENCODER_k10_FPS:
3981 case M4ENCODER_k15_FPS:
3982 case M4ENCODER_k30_FPS:
3983 /* OK */
3984 break;
3985
3986 default:
3987 M4OSA_TRACE1_0(
3988 "M4MCS_setOutputParams():\
3989 returning M4MCS_ERR_INVALID_VIDEO_FRAME_RATE_FOR_H263");
3990 return M4MCS_ERR_INVALID_VIDEO_FRAME_RATE_FOR_H263;
3991 }
3992 }
3993 }
3994
3995 /* Set audio parameters */
3996 if( pC->noaudio == M4OSA_FALSE )
3997 {
3998 /**
3999 * Check Audio Format correctness */
4000 switch( pParams->OutputAudioFormat )
4001 {
4002 case M4VIDEOEDITING_kAMR_NB:
4003
4004 err = M4MCS_setCurrentAudioEncoder(pContext,
4005 pParams->OutputAudioFormat);
4006 M4ERR_CHECK_RETURN(err);
4007
4008 pC->AudioEncParams.Format = M4ENCODER_kAMRNB;
4009 pC->AudioEncParams.Frequency = M4ENCODER_k8000Hz;
4010 pC->AudioEncParams.ChannelNum = M4ENCODER_kMono;
4011 pC->AudioEncParams.SpecifParam.AmrSID = M4ENCODER_kAmrNoSID;
4012 break;
4013
4014 case M4VIDEOEDITING_kAAC:
4015
4016 err = M4MCS_setCurrentAudioEncoder(pContext,
4017 pParams->OutputAudioFormat);
4018 M4ERR_CHECK_RETURN(err);
4019
4020 pC->AudioEncParams.Format = M4ENCODER_kAAC;
4021 pC->AudioEncParams.Frequency = M4ENCODER_k16000Hz;
4022
4023 switch( pParams->OutputAudioSamplingFrequency )
4024 {
4025 case M4VIDEOEDITING_k8000_ASF:
4026 pC->AudioEncParams.Frequency = M4ENCODER_k8000Hz;
4027 break;
4028
4029 case M4VIDEOEDITING_k16000_ASF:
4030 pC->AudioEncParams.Frequency = M4ENCODER_k16000Hz;
4031 break;
4032
4033 case M4VIDEOEDITING_k22050_ASF:
4034 pC->AudioEncParams.Frequency = M4ENCODER_k22050Hz;
4035 break;
4036
4037 case M4VIDEOEDITING_k24000_ASF:
4038 pC->AudioEncParams.Frequency = M4ENCODER_k24000Hz;
4039 break;
4040
4041 case M4VIDEOEDITING_k32000_ASF:
4042 pC->AudioEncParams.Frequency = M4ENCODER_k32000Hz;
4043 break;
4044
4045 case M4VIDEOEDITING_k44100_ASF:
4046 pC->AudioEncParams.Frequency = M4ENCODER_k44100Hz;
4047 break;
4048
4049 case M4VIDEOEDITING_k48000_ASF:
4050 pC->AudioEncParams.Frequency = M4ENCODER_k48000Hz;
4051 break;
4052
4053 case M4VIDEOEDITING_k11025_ASF:
4054 case M4VIDEOEDITING_k12000_ASF:
4055 case M4VIDEOEDITING_kDefault_ASF:
4056 break;
4057 }
4058 pC->AudioEncParams.ChannelNum =
4059 (pParams->bAudioMono == M4OSA_TRUE) ? \
4060 M4ENCODER_kMono : M4ENCODER_kStereo;
4061 pC->AudioEncParams.SpecifParam.AacParam.Regulation =
4062 M4ENCODER_kAacRegulNone; //M4ENCODER_kAacBitReservoir
4063 /* unused */
4064 pC->AudioEncParams.SpecifParam.AacParam.bIS = M4OSA_FALSE;
4065 pC->AudioEncParams.SpecifParam.AacParam.bMS = M4OSA_FALSE;
4066 pC->AudioEncParams.SpecifParam.AacParam.bPNS = M4OSA_FALSE;
4067 pC->AudioEncParams.SpecifParam.AacParam.bTNS = M4OSA_FALSE;
4068 /* TODO change into highspeed asap */
4069 pC->AudioEncParams.SpecifParam.AacParam.bHighSpeed =
4070 M4OSA_FALSE;
4071 break;
4072
4073 /*FlB 26.02.2009: add mp3 as mcs output format, add mp3 encoder*/
4074 case M4VIDEOEDITING_kMP3:
4075 err = M4MCS_setCurrentAudioEncoder(pContext,
4076 pParams->OutputAudioFormat);
4077 M4ERR_CHECK_RETURN(err);
4078
4079 pC->AudioEncParams.Format = M4ENCODER_kMP3;
4080 pC->AudioEncParams.ChannelNum =
4081 (pParams->bAudioMono == M4OSA_TRUE) ? \
4082 M4ENCODER_kMono : M4ENCODER_kStereo;
4083
4084 pC->AudioEncParams.Frequency = M4ENCODER_k16000Hz;
4085
4086 switch( pParams->OutputAudioSamplingFrequency )
4087 {
4088 case M4VIDEOEDITING_k8000_ASF:
4089 pC->AudioEncParams.Frequency = M4ENCODER_k8000Hz;
4090 break;
4091
4092 case M4VIDEOEDITING_k11025_ASF:
4093 pC->AudioEncParams.Frequency = M4ENCODER_k11025Hz;
4094 break;
4095
4096 case M4VIDEOEDITING_k12000_ASF:
4097 pC->AudioEncParams.Frequency = M4ENCODER_k12000Hz;
4098 break;
4099
4100 case M4VIDEOEDITING_k16000_ASF:
4101 pC->AudioEncParams.Frequency = M4ENCODER_k16000Hz;
4102 break;
4103
4104 case M4VIDEOEDITING_k22050_ASF:
4105 pC->AudioEncParams.Frequency = M4ENCODER_k22050Hz;
4106 break;
4107
4108 case M4VIDEOEDITING_k24000_ASF:
4109 pC->AudioEncParams.Frequency = M4ENCODER_k24000Hz;
4110 break;
4111
4112 case M4VIDEOEDITING_k32000_ASF:
4113 pC->AudioEncParams.Frequency = M4ENCODER_k32000Hz;
4114 break;
4115
4116 case M4VIDEOEDITING_k44100_ASF:
4117 pC->AudioEncParams.Frequency = M4ENCODER_k44100Hz;
4118 break;
4119
4120 case M4VIDEOEDITING_k48000_ASF:
4121 pC->AudioEncParams.Frequency = M4ENCODER_k48000Hz;
4122 break;
4123
4124 case M4VIDEOEDITING_kDefault_ASF:
4125 break;
4126 }
4127
4128 break;
4129
4130 case M4VIDEOEDITING_kNullAudio:
4131 if( pParams->pEffects == M4OSA_NULL || pParams->nbEffects == 0 )
4132 {
4133 /* no encoder needed */
4134 pC->AudioEncParams.Format = M4ENCODER_kAudioNULL;
4135 pC->AudioEncParams.Frequency =
4136 pC->pReaderAudioStream->m_samplingFrequency;
4137 pC->AudioEncParams.ChannelNum =
4138 (pC->pReaderAudioStream->m_nbChannels == 1) ? \
4139 M4ENCODER_kMono : M4ENCODER_kStereo;
4140 }
4141 else
4142 {
4143 pC->AudioEncParams.Frequency =
4144 pC->pReaderAudioStream->m_samplingFrequency;
4145 pC->AudioEncParams.ChannelNum =
4146 (pC->pReaderAudioStream->m_nbChannels == 1) ? \
4147 M4ENCODER_kMono : M4ENCODER_kStereo;
4148
4149 switch( pC->InputFileProperties.AudioStreamType )
4150 {
4151 case M4VIDEOEDITING_kAMR_NB:
4152 M4OSA_TRACE3_0(
4153 "M4MCS_setOutputParams calling \
4154 M4MCS_setCurrentAudioEncoder M4VIDEOEDITING_kNull, AMR");
4155 err = M4MCS_setCurrentAudioEncoder(pContext,
4156 pC->InputFileProperties.AudioStreamType);
4157 M4ERR_CHECK_RETURN(err);
4158
4159 pC->AudioEncParams.Format = M4ENCODER_kAMRNB;
4160 pC->AudioEncParams.Frequency = M4ENCODER_k8000Hz;
4161 pC->AudioEncParams.ChannelNum = M4ENCODER_kMono;
4162
4163 if( pC->pReaderAudioStream->m_samplingFrequency
4164 != 8000 )
4165 {
4166 pC->AudioEncParams.Format = M4ENCODER_kAMRNB;
4167 }
4168 pC->AudioEncParams.SpecifParam.AmrSID =
4169 M4ENCODER_kAmrNoSID;
4170 break;
4171
4172 case M4VIDEOEDITING_kAAC:
4173 M4OSA_TRACE3_0(
4174 "M4MCS_setOutputParams calling \
4175 M4MCS_setCurrentAudioEncoder M4VIDEOEDITING_kNull, AAC");
4176 err = M4MCS_setCurrentAudioEncoder(pContext,
4177 pC->InputFileProperties.AudioStreamType);
4178 M4ERR_CHECK_RETURN(err);
4179
4180 pC->AudioEncParams.Format = M4ENCODER_kAAC;
4181 pC->AudioEncParams.SpecifParam.AacParam.Regulation =
4182 M4ENCODER_kAacRegulNone; //M4ENCODER_kAacBitReservoir
4183 pC->AudioEncParams.Frequency = M4ENCODER_k16000Hz;
4184 pC->AudioEncParams.Frequency = M4ENCODER_k16000Hz;
4185
4186 switch( pC->pReaderAudioStream->
4187 m_samplingFrequency )
4188 {
4189 case 16000:
4190 pC->AudioEncParams.Frequency =
4191 M4ENCODER_k16000Hz;
4192 break;
4193
4194 case 22050:
4195 pC->AudioEncParams.Frequency =
4196 M4ENCODER_k22050Hz;
4197 break;
4198
4199 case 24000:
4200 pC->AudioEncParams.Frequency =
4201 M4ENCODER_k24000Hz;
4202 break;
4203
4204 case 32000:
4205 pC->AudioEncParams.Frequency =
4206 M4ENCODER_k32000Hz;
4207 break;
4208
4209 case 44100:
4210 pC->AudioEncParams.Frequency =
4211 M4ENCODER_k44100Hz;
4212 break;
4213
4214 case 48000:
4215 pC->AudioEncParams.Frequency =
4216 M4ENCODER_k48000Hz;
4217 break;
4218
4219 default:
4220 pC->AudioEncParams.Format = M4ENCODER_kAAC;
4221 break;
4222 }
4223 /* unused */
4224 pC->AudioEncParams.SpecifParam.AacParam.bIS =
4225 M4OSA_FALSE;
4226 pC->AudioEncParams.SpecifParam.AacParam.bMS =
4227 M4OSA_FALSE;
4228 pC->AudioEncParams.SpecifParam.AacParam.bPNS =
4229 M4OSA_FALSE;
4230 pC->AudioEncParams.SpecifParam.AacParam.bTNS =
4231 M4OSA_FALSE;
4232 /* TODO change into highspeed asap */
4233 pC->AudioEncParams.SpecifParam.AacParam.bHighSpeed =
4234 M4OSA_FALSE;
4235 break;
4236
4237 case M4VIDEOEDITING_kMP3:
4238 M4OSA_TRACE3_0(
4239 "M4MCS_setOutputParams calling\
4240 M4MCS_setCurrentAudioEncoder M4VIDEOEDITING_kNull, MP3");
4241 err = M4MCS_setCurrentAudioEncoder(pContext,
4242 pC->InputFileProperties.AudioStreamType);
4243 M4ERR_CHECK_RETURN(err);
4244
4245 pC->AudioEncParams.Format = M4ENCODER_kMP3;
4246 pC->AudioEncParams.Frequency = M4ENCODER_k16000Hz;
4247
4248 switch( pC->pReaderAudioStream->
4249 m_samplingFrequency )
4250 {
4251 case 8000:
4252 pC->AudioEncParams.Frequency =
4253 M4ENCODER_k8000Hz;
4254 break;
4255
4256 case 16000:
4257 pC->AudioEncParams.Frequency =
4258 M4ENCODER_k16000Hz;
4259 break;
4260
4261 case 22050:
4262 pC->AudioEncParams.Frequency =
4263 M4ENCODER_k22050Hz;
4264 break;
4265
4266 case 24000:
4267 pC->AudioEncParams.Frequency =
4268 M4ENCODER_k24000Hz;
4269 break;
4270
4271 case 32000:
4272 pC->AudioEncParams.Frequency =
4273 M4ENCODER_k32000Hz;
4274 break;
4275
4276 case 44100:
4277 pC->AudioEncParams.Frequency =
4278 M4ENCODER_k44100Hz;
4279 break;
4280
4281 case 48000:
4282 pC->AudioEncParams.Frequency =
4283 M4ENCODER_k48000Hz;
4284 break;
4285
4286 default:
4287 pC->AudioEncParams.Format = M4ENCODER_kMP3;
4288 break;
4289 }
4290 break;
4291
4292 case M4VIDEOEDITING_kEVRC:
4293 case M4VIDEOEDITING_kUnsupportedAudio:
4294 default:
4295 M4OSA_TRACE1_1(
4296 "M4MCS_setOutputParams: Output audio format (%d) is\
4297 incompatible with audio effects, returning \
4298 M4MCS_ERR_UNDEFINED_OUTPUT_AUDIO_FORMAT",
4299 pC->InputFileProperties.AudioStreamType);
4300 return M4MCS_ERR_UNDEFINED_OUTPUT_AUDIO_FORMAT;
4301 }
4302 }
4303 break;
4304 /* EVRC
4305 // case M4VIDEOEDITING_kEVRC:
4306 //
4307 // err = M4MCS_setCurrentAudioEncoder(pContext, pParams->\
4308 // OutputAudioFormat);
4309 // M4ERR_CHECK_RETURN(err);
4310 //
4311 // pC->AudioEncParams.Format = M4ENCODER_kEVRC;
4312 // pC->AudioEncParams.Frequency = M4ENCODER_k8000Hz;
4313 // pC->AudioEncParams.ChannelNum = M4ENCODER_kMono;
4314 // break; */
4315
4316 default:
4317 M4OSA_TRACE1_1("M4MCS_setOutputParams: Undefined output audio format (%d),\
4318 returning M4MCS_ERR_UNDEFINED_OUTPUT_AUDIO_FORMAT",
4319 pParams->OutputAudioFormat);
4320 return M4MCS_ERR_UNDEFINED_OUTPUT_AUDIO_FORMAT;
4321 }
4322 }
4323
4324 if( pParams->pOutputPCMfile != M4OSA_NULL )
4325 {
4326 pC->pOutputPCMfile = pParams->pOutputPCMfile;
4327
4328 /* Open output PCM file */
4329 pC->pOsaFileWritPtr->openWrite(&(pC->pOutputPCMfile),
4330 pParams->pOutputPCMfile, M4OSA_kFileWrite);
4331 }
4332 else
4333 {
4334 pC->pOutputPCMfile = M4OSA_NULL;
4335 }
4336
4337 /*Store media rendering parameter into the internal context*/
4338 pC->MediaRendering = pParams->MediaRendering;
4339
4340 /* Add audio effects*/
4341 /*Copy MCS effects structure into internal context*/
4342 if( pParams->nbEffects > 0 )
4343 {
4344 M4OSA_UInt32 j = 0;
4345 pC->nbEffects = pParams->nbEffects;
4346 pC->pEffects = (M4MCS_EffectSettings *)M4OSA_32bitAlignedMalloc(pC->nbEffects \
4347 *sizeof(M4MCS_EffectSettings), M4MCS,
4348 (M4OSA_Char *)"Allocation of effects list");
4349
4350 if( pC->pEffects == M4OSA_NULL )
4351 {
4352 M4OSA_TRACE1_0("M4MCS_setOutputParams(): allocation error");
4353 return M4ERR_ALLOC;
4354 }
4355
4356 for ( j = 0; j < pC->nbEffects; j++ )
4357 {
4358 /* Copy effect to "local" structure */
4359 memcpy((void *) &(pC->pEffects[j]),
4360 (void *) &(pParams->pEffects[j]),
4361 sizeof(M4MCS_EffectSettings));
4362
4363 switch( pC->pEffects[j].AudioEffectType )
4364 {
4365 case M4MCS_kAudioEffectType_None:
4366 M4OSA_TRACE3_1(
4367 "M4MCS_setOutputParams(): effect type %i is None", j);
4368 pC->pEffects[j].pExtAudioEffectFctCtxt = M4OSA_NULL;
4369 pC->pEffects[j].ExtAudioEffectFct = M4OSA_NULL;
4370 break;
4371
4372 case M4MCS_kAudioEffectType_FadeIn:
4373 M4OSA_TRACE3_1(
4374 "M4MCS_setOutputParams(): effect type %i is FadeIn", j);
4375 pC->pEffects[j].pExtAudioEffectFctCtxt = M4OSA_NULL;
4376 pC->pEffects[j].ExtAudioEffectFct =
4377 M4MCS_editAudioEffectFct_FadeIn;
4378 break;
4379
4380 case M4MCS_kAudioEffectType_FadeOut:
4381 M4OSA_TRACE3_1(
4382 "M4MCS_setOutputParams(): effect type %i is FadeOut",
4383 j);
4384 pC->pEffects[j].pExtAudioEffectFctCtxt = M4OSA_NULL;
4385 pC->pEffects[j].ExtAudioEffectFct =
4386 M4MCS_editAudioEffectFct_FadeOut;
4387 break;
4388
4389 case M4MCS_kAudioEffectType_External:
4390 M4OSA_TRACE3_1(
4391 "M4MCS_setOutputParams(): effect type %i is External",
4392 j);
4393
4394 if( pParams->pEffects != M4OSA_NULL )
4395 {
4396 if( pParams->pEffects[j].ExtAudioEffectFct
4397 == M4OSA_NULL )
4398 {
4399 M4OSA_TRACE1_1("M4MCS_setOutputParams(): no external effect function\
4400 associated to external effect number %i", j);
4401 return M4ERR_PARAMETER;
4402 }
4403 pC->pEffects[j].pExtAudioEffectFctCtxt =
4404 pParams->pEffects[j].pExtAudioEffectFctCtxt;
4405
4406 pC->pEffects[j].ExtAudioEffectFct =
4407 pParams->pEffects[j].ExtAudioEffectFct;
4408 }
4409
4410 break;
4411
4412 default:
4413 M4OSA_TRACE1_0(
4414 "M4MCS_setOutputParams(): effect type not recognized");
4415 return M4ERR_PARAMETER;
4416 }
4417 }
4418 }
4419 else
4420 {
4421 pC->nbEffects = 0;
4422 pC->pEffects = M4OSA_NULL;
4423 }
4424
4425 /**
4426 * Update state automaton */
4427 pC->State = M4MCS_kState_SET;
4428
4429 /**
4430 * Return with no error */
4431 M4OSA_TRACE3_0("M4MCS_setOutputParams(): returning M4NO_ERROR");
4432 return M4NO_ERROR;
4433 }
4434
4435 /**
4436 ******************************************************************************
4437 * M4OSA_ERR M4MCS_setEncodingParams(M4MCS_Context pContext, M4MCS_EncodingParams* pRates)
4438 * @brief Set the values of the encoding parameters
4439 * @note Must be called before M4MCS_checkParamsAndStart().
4440 * @param pContext (IN) MCS context
4441 * @param pRates (IN) Transcoding parameters
4442 * @return M4NO_ERROR: No error
4443 * @return M4ERR_PARAMETER: At least one parameter is M4OSA_NULL (debug only)
4444 * @return M4ERR_STATE: MCS is not in an appropriate state for this function to be called
4445 * @return M4MCS_ERR_AUDIOBITRATE_TOO_HIGH: Audio bitrate too high (we limit to 96 kbps)
4446 * @return M4MCS_ERR_AUDIOBITRATE_TOO_LOW: Audio bitrate is too low (16 kbps min for aac, 12.2
4447 * for amr, 8 for mp3)
4448 * @return M4MCS_ERR_BEGIN_CUT_EQUALS_END_CUT: Begin cut and End cut are equals
4449 * @return M4MCS_ERR_BEGIN_CUT_LARGER_THAN_DURATION: Begin cut time is larger than the input clip
4450 * duration
4451 * @return M4MCS_ERR_END_CUT_SMALLER_THAN_BEGIN_CUT: End cut time is smaller than begin cut time
4452 * @return M4MCS_ERR_MAXFILESIZE_TOO_SMALL: Not enough space to store whole output file at given
4453 * bitrates
4454 * @return M4MCS_ERR_VIDEOBITRATE_TOO_HIGH: Video bitrate too high (we limit to 800 kbps)
4455 * @return M4MCS_ERR_VIDEOBITRATE_TOO_LOW: Video bitrate too low
4456 ******************************************************************************
4457 */
M4MCS_setEncodingParams(M4MCS_Context pContext,M4MCS_EncodingParams * pRates)4458 M4OSA_ERR M4MCS_setEncodingParams( M4MCS_Context pContext,
4459 M4MCS_EncodingParams *pRates )
4460 {
4461 M4MCS_InternalContext *pC = (M4MCS_InternalContext *)(pContext);
4462 M4OSA_UInt32 j = 0;
4463
4464 M4OSA_TRACE2_2(
4465 "M4MCS_setEncodingParams called with pContext=0x%x, pRates=0x%x",
4466 pContext, pRates);
4467
4468 /**
4469 * Check input parameters */
4470 M4OSA_DEBUG_IF2((M4OSA_NULL == pContext), M4ERR_PARAMETER,
4471 "M4MCS_setEncodingParams: pContext is M4OSA_NULL");
4472 M4OSA_DEBUG_IF2((M4OSA_NULL == pRates), M4ERR_PARAMETER,
4473 "M4MCS_setEncodingParams: pRates is M4OSA_NULL");
4474
4475 #ifdef M4MCS_SUPPORT_STILL_PICTURE
4476
4477 if( pC->m_bIsStillPicture )
4478 {
4479 /**
4480 * Call the corresponding still picture MCS function*/
4481 return M4MCS_stillPicSetEncodingParams(pC, pRates);
4482 }
4483
4484 #endif /*M4MCS_SUPPORT_STILL_PICTURE*/
4485
4486 /**
4487 * Check state automaton */
4488
4489 if( M4MCS_kState_SET != pC->State )
4490 {
4491 M4OSA_TRACE1_1(
4492 "M4MCS_setEncodingParams(): Wrong State (%d), returning M4ERR_STATE",
4493 pC->State);
4494 return M4ERR_STATE;
4495 }
4496
4497 /* Set given values */
4498 pC->uiVideoBitrate = pRates->OutputVideoBitrate;
4499 pC->uiAudioBitrate = pRates->OutputAudioBitrate;
4500 pC->uiBeginCutTime = pRates->BeginCutTime;
4501 pC->uiEndCutTime = pRates->EndCutTime;
4502 pC->uiMaxFileSize = pRates->OutputFileSize;
4503
4504 /**
4505 * Check begin cut time validity */
4506 if( pC->uiBeginCutTime >= pC->InputFileProperties.uiClipDuration )
4507 {
4508 M4OSA_TRACE1_2("M4MCS_setEncodingParams(): Begin cut larger than duration (%d>%d),\
4509 returning M4MCS_ERR_BEGIN_CUT_LARGER_THAN_DURATION",
4510 pC->uiBeginCutTime, pC->InputFileProperties.uiClipDuration);
4511 return M4MCS_ERR_BEGIN_CUT_LARGER_THAN_DURATION;
4512 }
4513
4514 /**
4515 * If end cut time is too large, we set it to the clip duration */
4516 if( pC->uiEndCutTime > pC->InputFileProperties.uiClipDuration )
4517 {
4518 pC->uiEndCutTime = pC->InputFileProperties.uiClipDuration;
4519 }
4520
4521 /**
4522 * Check end cut time validity */
4523 if( pC->uiEndCutTime > 0 )
4524 {
4525 if( pC->uiEndCutTime < pC->uiBeginCutTime )
4526 {
4527 M4OSA_TRACE1_2("M4MCS_setEncodingParams(): Begin cut greater than end cut (%d,%d), \
4528 returning M4MCS_ERR_END_CUT_SMALLER_THAN_BEGIN_CUT",
4529 pC->uiBeginCutTime, pC->uiEndCutTime);
4530 return M4MCS_ERR_END_CUT_SMALLER_THAN_BEGIN_CUT;
4531 }
4532
4533 if( pC->uiEndCutTime == pC->uiBeginCutTime )
4534 {
4535 M4OSA_TRACE1_2("M4MCS_setEncodingParams(): Begin and End cuts are equal (%d,%d),\
4536 returning M4MCS_ERR_BEGIN_CUT_EQUALS_END_CUT",
4537 pC->uiBeginCutTime, pC->uiEndCutTime);
4538 return M4MCS_ERR_BEGIN_CUT_EQUALS_END_CUT;
4539 }
4540 }
4541
4542 /**
4543 * FlB 2009.03.04: check audio effects start time and duration validity*/
4544 for ( j = 0; j < pC->nbEffects; j++ )
4545 {
4546 M4OSA_UInt32 outputEndCut = pC->uiEndCutTime;
4547
4548 if( pC->uiEndCutTime == 0 )
4549 {
4550 outputEndCut = pC->InputFileProperties.uiClipDuration;
4551 }
4552
4553 if( pC->pEffects[j].uiStartTime > (outputEndCut - pC->uiBeginCutTime) )
4554 {
4555 M4OSA_TRACE1_2("M4MCS_setEncodingParams(): Effects start time is larger than\
4556 duration (%d,%d), returning M4ERR_PARAMETER",
4557 pC->pEffects[j].uiStartTime,
4558 (pC->uiEndCutTime - pC->uiBeginCutTime));
4559 return M4ERR_PARAMETER;
4560 }
4561
4562 if( pC->pEffects[j].uiStartTime + pC->pEffects[j].uiDuration > \
4563 (outputEndCut - pC->uiBeginCutTime) )
4564 {
4565 /* Re-adjust the effect duration until the end of the output clip*/
4566 pC->pEffects[j].uiDuration = (outputEndCut - pC->uiBeginCutTime) - \
4567 pC->pEffects[j].uiStartTime;
4568 }
4569 }
4570
4571 /* Check audio bitrate consistency */
4572 if( ( pC->noaudio == M4OSA_FALSE)
4573 && (pC->AudioEncParams.Format != M4ENCODER_kAudioNULL) )
4574 {
4575 if( pC->uiAudioBitrate != M4VIDEOEDITING_kUndefinedBitrate )
4576 {
4577 if( pC->AudioEncParams.Format == M4ENCODER_kAMRNB )
4578 {
4579 if( pC->uiAudioBitrate > M4VIDEOEDITING_k12_2_KBPS )
4580 return M4MCS_ERR_AUDIOBITRATE_TOO_HIGH;
4581
4582 if( pC->uiAudioBitrate < M4VIDEOEDITING_k12_2_KBPS )
4583 return M4MCS_ERR_AUDIOBITRATE_TOO_LOW;
4584 }
4585 //EVRC
4586 // else if(pC->AudioEncParams.Format == M4ENCODER_kEVRC)
4587 // {
4588 // if(pC->uiAudioBitrate > M4VIDEOEDITING_k9_2_KBPS)
4589 // return M4MCS_ERR_AUDIOBITRATE_TOO_HIGH;
4590 // if(pC->uiAudioBitrate < M4VIDEOEDITING_k9_2_KBPS)
4591 // return M4MCS_ERR_AUDIOBITRATE_TOO_LOW;
4592 // }
4593 /*FlB 26.02.2009: add mp3 as mcs output format, add mp3 encoder*/
4594 else if( pC->AudioEncParams.Format == M4ENCODER_kMP3 )
4595 {
4596 if( pC->AudioEncParams.Frequency >= M4ENCODER_k32000Hz )
4597 {
4598 /*Mpeg layer 1*/
4599 if( pC->uiAudioBitrate > 320000 )
4600 return M4MCS_ERR_AUDIOBITRATE_TOO_HIGH;
4601
4602 if( pC->uiAudioBitrate < 32000 )
4603 return M4MCS_ERR_AUDIOBITRATE_TOO_LOW;
4604 }
4605 else if( pC->AudioEncParams.Frequency >= M4ENCODER_k16000Hz )
4606 {
4607 /*Mpeg layer 2*/
4608 if( pC->uiAudioBitrate > 160000 )
4609 return M4MCS_ERR_AUDIOBITRATE_TOO_HIGH;
4610
4611 if( ( pC->uiAudioBitrate < 8000
4612 && pC->AudioEncParams.ChannelNum == M4ENCODER_kMono)
4613 || (pC->uiAudioBitrate < 16000
4614 && pC->AudioEncParams.ChannelNum
4615 == M4ENCODER_kStereo) )
4616 return M4MCS_ERR_AUDIOBITRATE_TOO_LOW;
4617 }
4618 else if( pC->AudioEncParams.Frequency == M4ENCODER_k8000Hz
4619 || pC->AudioEncParams.Frequency == M4ENCODER_k11025Hz
4620 || pC->AudioEncParams.Frequency == M4ENCODER_k12000Hz )
4621 {
4622 /*Mpeg layer 2.5*/
4623 if( pC->uiAudioBitrate > 64000 )
4624 return M4MCS_ERR_AUDIOBITRATE_TOO_HIGH;
4625
4626 if( ( pC->uiAudioBitrate < 8000
4627 && pC->AudioEncParams.ChannelNum == M4ENCODER_kMono)
4628 || (pC->uiAudioBitrate < 16000
4629 && pC->AudioEncParams.ChannelNum
4630 == M4ENCODER_kStereo) )
4631 return M4MCS_ERR_AUDIOBITRATE_TOO_LOW;
4632 }
4633 else
4634 {
4635 M4OSA_TRACE1_1("M4MCS_setEncodingParams: MP3 audio sampling frequency error\
4636 (%d)", pC->AudioEncParams.Frequency);
4637 return M4ERR_PARAMETER;
4638 }
4639 }
4640 else
4641 {
4642 if( pC->uiAudioBitrate > M4VIDEOEDITING_k192_KBPS )
4643 return M4MCS_ERR_AUDIOBITRATE_TOO_HIGH;
4644
4645 if( pC->AudioEncParams.ChannelNum == M4ENCODER_kMono )
4646 {
4647 if( pC->uiAudioBitrate < M4VIDEOEDITING_k16_KBPS )
4648 return M4MCS_ERR_AUDIOBITRATE_TOO_LOW;
4649 }
4650 else
4651 {
4652 if( pC->uiAudioBitrate < M4VIDEOEDITING_k32_KBPS )
4653 return M4MCS_ERR_AUDIOBITRATE_TOO_LOW;
4654 }
4655 }
4656 }
4657 }
4658 else
4659 {
4660 /* NULL audio : copy input file bitrate */
4661 pC->uiAudioBitrate = pC->InputFileProperties.uiAudioBitrate;
4662 }
4663
4664 /* Check video bitrate consistency */
4665 if( ( pC->novideo == M4OSA_FALSE)
4666 && (pC->EncodingVideoFormat != M4ENCODER_kNULL) )
4667 {
4668 if( pC->uiVideoBitrate != M4VIDEOEDITING_kUndefinedBitrate )
4669 {
4670 if( pC->uiVideoBitrate > M4VIDEOEDITING_k8_MBPS )
4671 return M4MCS_ERR_VIDEOBITRATE_TOO_HIGH;
4672
4673 if( pC->uiVideoBitrate < M4VIDEOEDITING_k16_KBPS )
4674 return M4MCS_ERR_VIDEOBITRATE_TOO_LOW;
4675 }
4676 }
4677 else
4678 {
4679 /* NULL video : copy input file bitrate */
4680 pC->uiVideoBitrate = pC->InputFileProperties.uiVideoBitrate;
4681 }
4682
4683 if( pRates->OutputVideoTimescale <= 30000
4684 && pRates->OutputVideoTimescale > 0 )
4685 {
4686 pC->outputVideoTimescale = pRates->OutputVideoTimescale;
4687 }
4688
4689 /* Check file size */
4690 return M4MCS_intCheckMaxFileSize(pC);
4691 }
4692
4693 /**
4694 ******************************************************************************
4695 * M4OSA_ERR M4MCS_getExtendedEncodingParams(M4MCS_Context pContext, M4MCS_EncodingParams* pRates)
4696 * @brief Get the extended values of the encoding parameters
4697 * @note Could be called after M4MCS_setEncodingParams.
4698 * @param pContext (IN) MCS context
4699 * @param pRates (OUT) Transcoding parameters
4700 * @return M4NO_ERROR: No error
4701 * @return M4ERR_PARAMETER: At least one parameter is M4OSA_NULL (debug only)
4702 * @return M4ERR_STATE: MCS is not in an appropriate state for this function to be called
4703 * @return M4MCS_ERR_BEGIN_CUT_EQUALS_END_CUT: Encoding settings would produce a null duration
4704 * clip = encoding is impossible
4705 ******************************************************************************
4706 */
M4MCS_getExtendedEncodingParams(M4MCS_Context pContext,M4MCS_EncodingParams * pRates)4707 M4OSA_ERR M4MCS_getExtendedEncodingParams( M4MCS_Context pContext,
4708 M4MCS_EncodingParams *pRates )
4709 {
4710 M4MCS_InternalContext *pC = (M4MCS_InternalContext *)(pContext);
4711
4712 M4OSA_Int32 minaudiobitrate;
4713 M4OSA_Int32 minvideobitrate;
4714 M4OSA_Int32 maxcombinedbitrate;
4715
4716 M4OSA_Int32 calcbitrate;
4717
4718 M4OSA_UInt32 maxduration;
4719 M4OSA_UInt32 calcduration;
4720
4721 M4OSA_Bool fixed_audio = M4OSA_FALSE;
4722 M4OSA_Bool fixed_video = M4OSA_FALSE;
4723
4724 #ifdef M4MCS_SUPPORT_STILL_PICTURE
4725
4726 if( pC->m_bIsStillPicture )
4727 {
4728 /**
4729 * Call the corresponding still picture MCS function*/
4730 return M4MCS_stillPicGetExtendedEncodingParams(pC, pRates);
4731 }
4732
4733 #endif /*M4MCS_SUPPORT_STILL_PICTURE*/
4734
4735 pRates->OutputVideoBitrate =
4736 M4MCS_intGetNearestBitrate(pC->uiVideoBitrate, 0);
4737 pRates->OutputAudioBitrate =
4738 M4MCS_intGetNearestBitrate(pC->uiAudioBitrate, 0);
4739 pRates->BeginCutTime = pC->uiBeginCutTime;
4740 pRates->EndCutTime = pC->uiEndCutTime;
4741 pRates->OutputFileSize = pC->uiMaxFileSize;
4742
4743 /**
4744 * Check state automaton */
4745 if( M4MCS_kState_SET != pC->State )
4746 {
4747 M4OSA_TRACE1_1("M4MCS_getExtendedEncodingParams(): Wrong State (%d),\
4748 returning M4ERR_STATE", pC->State);
4749 return M4ERR_STATE;
4750 }
4751
4752 /* Compute min audio bitrate */
4753 if( pC->noaudio )
4754 {
4755 fixed_audio = M4OSA_TRUE;
4756 pRates->OutputAudioBitrate = 0;
4757 minaudiobitrate = 0;
4758 }
4759 else if( pC->AudioEncParams.Format == M4ENCODER_kAudioNULL )
4760 {
4761 fixed_audio = M4OSA_TRUE;
4762 pRates->OutputAudioBitrate = pC->InputFileProperties.uiAudioBitrate;
4763 minaudiobitrate = pC->InputFileProperties.uiAudioBitrate;
4764 }
4765 else
4766 {
4767 if( pC->AudioEncParams.Format == M4ENCODER_kAMRNB )
4768 {
4769 fixed_audio = M4OSA_TRUE;
4770 pRates->OutputAudioBitrate = M4VIDEOEDITING_k12_2_KBPS;
4771 minaudiobitrate = M4VIDEOEDITING_k12_2_KBPS;
4772 }
4773 //EVRC
4774 // if(pC->AudioEncParams.Format == M4ENCODER_kEVRC)
4775 // {
4776 // fixed_audio = M4OSA_TRUE;
4777 // pRates->OutputAudioBitrate = M4VIDEOEDITING_k9_2_KBPS;
4778 // minaudiobitrate = M4VIDEOEDITING_k9_2_KBPS;
4779 // }
4780 /*FlB 26.02.2009: add mp3 as mcs output format*/
4781 else if( pC->AudioEncParams.Format == M4ENCODER_kMP3 )
4782 {
4783 minaudiobitrate =
4784 M4VIDEOEDITING_k32_KBPS; /*Default min audio bitrate for MPEG layer 1,
4785 for both mono and stereo channels*/
4786 }
4787 else
4788 {
4789 minaudiobitrate = (pC->AudioEncParams.ChannelNum == M4ENCODER_kMono)
4790 ? M4VIDEOEDITING_k16_KBPS : M4VIDEOEDITING_k32_KBPS;
4791 }
4792 }
4793
4794 /* Check audio bitrate is in the correct range */
4795 if( fixed_audio == M4OSA_FALSE )
4796 {
4797 if( ( pC->uiAudioBitrate > 0)
4798 && (pRates->OutputAudioBitrate < minaudiobitrate) )
4799 {
4800 pRates->OutputAudioBitrate = minaudiobitrate;
4801 }
4802
4803 if( pRates->OutputAudioBitrate > M4VIDEOEDITING_k96_KBPS )
4804 {
4805 pRates->OutputAudioBitrate = M4VIDEOEDITING_k96_KBPS;
4806 }
4807 }
4808
4809 /* Compute min video bitrate */
4810 if( pC->novideo )
4811 {
4812 fixed_video = M4OSA_TRUE;
4813 pRates->OutputVideoBitrate = 0;
4814 minvideobitrate = 0;
4815 }
4816 else if( pC->EncodingVideoFormat == M4ENCODER_kNULL )
4817 {
4818 fixed_video = M4OSA_TRUE;
4819 pRates->OutputVideoBitrate = pC->InputFileProperties.uiVideoBitrate;
4820 minvideobitrate = pC->InputFileProperties.uiVideoBitrate;
4821 }
4822 else
4823 {
4824 minvideobitrate = M4VIDEOEDITING_k16_KBPS;
4825 }
4826
4827 /* Check video bitrate is in the correct range */
4828 if( fixed_video == M4OSA_FALSE )
4829 {
4830 if( ( pC->uiVideoBitrate > 0)
4831 && (pRates->OutputVideoBitrate < minvideobitrate) )
4832 {
4833 pRates->OutputVideoBitrate = minvideobitrate;
4834 }
4835 /*+ New Encoder bitrates */
4836 if( pRates->OutputVideoBitrate > M4VIDEOEDITING_k8_MBPS )
4837 {
4838 pRates->OutputVideoBitrate = M4VIDEOEDITING_k8_MBPS;
4839 }
4840 /*- New Encoder bitrates */
4841 }
4842
4843 /* Check cut times are in correct range */
4844 if( ( pRates->BeginCutTime >= pC->InputFileProperties.uiClipDuration)
4845 || (( pRates->BeginCutTime >= pRates->EndCutTime)
4846 && (pRates->EndCutTime > 0)) )
4847 {
4848 pRates->BeginCutTime = 0;
4849 pRates->EndCutTime = 0;
4850 }
4851
4852 if( pRates->EndCutTime == 0 )
4853 calcduration =
4854 pC->InputFileProperties.uiClipDuration - pRates->BeginCutTime;
4855 else
4856 calcduration = pRates->EndCutTime - pRates->BeginCutTime;
4857
4858 /* priority 1 : max file size */
4859 if( pRates->OutputFileSize == 0 )
4860 {
4861 /* we can put maximum values for all undefined parameters */
4862 if( pRates->EndCutTime == 0 )
4863 {
4864 pRates->EndCutTime = pC->InputFileProperties.uiClipDuration;
4865 }
4866
4867 if( ( pRates->OutputAudioBitrate == M4VIDEOEDITING_kUndefinedBitrate)
4868 && (fixed_audio == M4OSA_FALSE) )
4869 {
4870 pRates->OutputAudioBitrate = M4VIDEOEDITING_k96_KBPS;
4871 }
4872
4873 if( ( pRates->OutputVideoBitrate == M4VIDEOEDITING_kUndefinedBitrate)
4874 && (fixed_video == M4OSA_FALSE) )
4875 {
4876 /*+ New Encoder bitrates */
4877 pRates->OutputVideoBitrate = M4VIDEOEDITING_k8_MBPS;
4878 /*- New Encoder bitrates */
4879 }
4880 }
4881 else
4882 {
4883 /* compute max duration */
4884 maxduration = (M4OSA_UInt32)(pRates->OutputFileSize
4885 / M4MCS_MOOV_OVER_FILESIZE_RATIO
4886 / (minvideobitrate + minaudiobitrate) * 8000.0);
4887
4888 if( maxduration
4889 + pRates->BeginCutTime > pC->InputFileProperties.uiClipDuration )
4890 {
4891 maxduration =
4892 pC->InputFileProperties.uiClipDuration - pRates->BeginCutTime;
4893 }
4894
4895 /* priority 2 : cut times */
4896 if( ( pRates->BeginCutTime > 0) || (pRates->EndCutTime > 0) )
4897 {
4898 if( calcduration > maxduration )
4899 {
4900 calcduration = maxduration;
4901 }
4902
4903 if( calcduration == 0 )
4904 {
4905 return M4MCS_ERR_BEGIN_CUT_EQUALS_END_CUT;
4906 }
4907
4908 maxcombinedbitrate = (M4OSA_UInt32)(pRates->OutputFileSize
4909 / M4MCS_MOOV_OVER_FILESIZE_RATIO / (calcduration / 8000.0));
4910
4911 /* audio and video bitrates */
4912 if( ( pRates->OutputAudioBitrate
4913 == M4VIDEOEDITING_kUndefinedBitrate)
4914 && (pRates->OutputVideoBitrate
4915 == M4VIDEOEDITING_kUndefinedBitrate) )
4916 {
4917 /* set audio = 1/3 and video = 2/3 */
4918 if( fixed_audio == M4OSA_FALSE )
4919 {
4920 if( pC->novideo )
4921 pRates->OutputAudioBitrate =
4922 M4MCS_intGetNearestBitrate(maxcombinedbitrate, 0);
4923 else
4924 pRates->OutputAudioBitrate =
4925 M4MCS_intGetNearestBitrate(maxcombinedbitrate / 3,
4926 0);
4927
4928 if( pRates->OutputAudioBitrate < minaudiobitrate )
4929 pRates->OutputAudioBitrate = minaudiobitrate;
4930
4931 if( pRates->OutputAudioBitrate > M4VIDEOEDITING_k96_KBPS )
4932 pRates->OutputAudioBitrate = M4VIDEOEDITING_k96_KBPS;
4933 }
4934
4935 if( fixed_video == M4OSA_FALSE )
4936 {
4937 pRates->OutputVideoBitrate =
4938 M4MCS_intGetNearestBitrate(maxcombinedbitrate
4939 - pRates->OutputAudioBitrate, 0);
4940
4941 if( pRates->OutputVideoBitrate < minvideobitrate )
4942 pRates->OutputVideoBitrate = minvideobitrate;
4943
4944 if( pRates->OutputVideoBitrate > M4VIDEOEDITING_k8_MBPS )
4945 pRates->OutputVideoBitrate =
4946 M4VIDEOEDITING_k8_MBPS; /*+ New Encoder
4947 bitrates */
4948 }
4949 }
4950 else
4951 {
4952 /* priority 3 : audio bitrate */
4953 if( pRates->OutputAudioBitrate
4954 != M4VIDEOEDITING_kUndefinedBitrate )
4955 {
4956 while( ( fixed_audio == M4OSA_FALSE)
4957 && (pRates->OutputAudioBitrate >= minaudiobitrate)
4958 && (pRates->OutputAudioBitrate
4959 + minvideobitrate > maxcombinedbitrate) )
4960 {
4961 pRates->OutputAudioBitrate =
4962 M4MCS_intGetNearestBitrate(
4963 pRates->OutputAudioBitrate, -1);
4964 }
4965
4966 if( ( fixed_audio == M4OSA_FALSE)
4967 && (pRates->OutputAudioBitrate < minaudiobitrate) )
4968 {
4969 pRates->OutputAudioBitrate = minaudiobitrate;
4970 }
4971
4972 calcbitrate = M4MCS_intGetNearestBitrate(
4973 maxcombinedbitrate
4974 - pRates->OutputAudioBitrate, 0);
4975
4976 if( calcbitrate < minvideobitrate )
4977 calcbitrate = minvideobitrate;
4978
4979 if( calcbitrate > M4VIDEOEDITING_k8_MBPS )
4980 calcbitrate = M4VIDEOEDITING_k8_MBPS;
4981
4982 if( ( fixed_video == M4OSA_FALSE)
4983 && (( pRates->OutputVideoBitrate
4984 == M4VIDEOEDITING_kUndefinedBitrate)
4985 || (pRates->OutputVideoBitrate > calcbitrate)) )
4986 {
4987 pRates->OutputVideoBitrate = calcbitrate;
4988 }
4989 }
4990 else
4991 {
4992 /* priority 4 : video bitrate */
4993 if( pRates->OutputVideoBitrate
4994 != M4VIDEOEDITING_kUndefinedBitrate )
4995 {
4996 while( ( fixed_video == M4OSA_FALSE)
4997 && (pRates->OutputVideoBitrate >= minvideobitrate)
4998 && (pRates->OutputVideoBitrate
4999 + minaudiobitrate > maxcombinedbitrate) )
5000 {
5001 pRates->OutputVideoBitrate =
5002 M4MCS_intGetNearestBitrate(
5003 pRates->OutputVideoBitrate, -1);
5004 }
5005
5006 if( ( fixed_video == M4OSA_FALSE)
5007 && (pRates->OutputVideoBitrate < minvideobitrate) )
5008 {
5009 pRates->OutputVideoBitrate = minvideobitrate;
5010 }
5011
5012 calcbitrate =
5013 M4MCS_intGetNearestBitrate(maxcombinedbitrate
5014 - pRates->OutputVideoBitrate, 0);
5015
5016 if( calcbitrate < minaudiobitrate )
5017 calcbitrate = minaudiobitrate;
5018
5019 if( calcbitrate > M4VIDEOEDITING_k96_KBPS )
5020 calcbitrate = M4VIDEOEDITING_k96_KBPS;
5021
5022 if( ( fixed_audio == M4OSA_FALSE)
5023 && (( pRates->OutputAudioBitrate
5024 == M4VIDEOEDITING_kUndefinedBitrate)
5025 || (pRates->OutputAudioBitrate > calcbitrate)) )
5026 {
5027 pRates->OutputAudioBitrate = calcbitrate;
5028 }
5029 }
5030 }
5031 }
5032 }
5033 else
5034 {
5035 /* priority 3 : audio bitrate */
5036 if( pRates->OutputAudioBitrate != M4VIDEOEDITING_kUndefinedBitrate )
5037 {
5038 /* priority 4 : video bitrate */
5039 if( pRates->OutputVideoBitrate
5040 != M4VIDEOEDITING_kUndefinedBitrate )
5041 {
5042 /* compute max duration */
5043 maxduration = (M4OSA_UInt32)(pRates->OutputFileSize
5044 / M4MCS_MOOV_OVER_FILESIZE_RATIO
5045 / (pRates->OutputVideoBitrate
5046 + pRates->OutputAudioBitrate) * 8000.0);
5047
5048 if( maxduration + pRates->BeginCutTime
5049 > pC->InputFileProperties.uiClipDuration )
5050 {
5051 maxduration = pC->InputFileProperties.uiClipDuration
5052 - pRates->BeginCutTime;
5053 }
5054
5055 if( calcduration > maxduration )
5056 {
5057 calcduration = maxduration;
5058 }
5059
5060 if( calcduration == 0 )
5061 {
5062 return M4MCS_ERR_BEGIN_CUT_EQUALS_END_CUT;
5063 }
5064 }
5065 else
5066 {
5067 /* start with min video bitrate */
5068 pRates->OutputVideoBitrate = minvideobitrate;
5069
5070 /* compute max duration */
5071 maxduration = (M4OSA_UInt32)(pRates->OutputFileSize
5072 / M4MCS_MOOV_OVER_FILESIZE_RATIO
5073 / (pRates->OutputVideoBitrate
5074 + pRates->OutputAudioBitrate) * 8000.0);
5075
5076 if( maxduration + pRates->BeginCutTime
5077 > pC->InputFileProperties.uiClipDuration )
5078 {
5079 maxduration = pC->InputFileProperties.uiClipDuration
5080 - pRates->BeginCutTime;
5081 }
5082
5083 if( calcduration > maxduration )
5084 {
5085 calcduration = maxduration;
5086 }
5087
5088 if( calcduration == 0 )
5089 {
5090 return M4MCS_ERR_BEGIN_CUT_EQUALS_END_CUT;
5091 }
5092
5093 /* search max possible video bitrate */
5094 maxcombinedbitrate = (M4OSA_UInt32)(pRates->OutputFileSize
5095 / M4MCS_MOOV_OVER_FILESIZE_RATIO
5096 / (calcduration / 8000.0));
5097
5098 while( ( fixed_video == M4OSA_FALSE)
5099 && (pRates->OutputVideoBitrate
5100 < M4VIDEOEDITING_k8_MBPS) ) /*+ New Encoder bitrates */
5101 {
5102 calcbitrate = M4MCS_intGetNearestBitrate(
5103 pRates->OutputVideoBitrate, +1);
5104
5105 if( calcbitrate
5106 + pRates->OutputAudioBitrate <= maxcombinedbitrate )
5107 pRates->OutputVideoBitrate = calcbitrate;
5108 else
5109 break;
5110 }
5111 }
5112 }
5113 else
5114 {
5115 /* priority 4 : video bitrate */
5116 if( pRates->OutputVideoBitrate
5117 != M4VIDEOEDITING_kUndefinedBitrate )
5118 {
5119 /* start with min audio bitrate */
5120 pRates->OutputAudioBitrate = minaudiobitrate;
5121
5122 /* compute max duration */
5123 maxduration = (M4OSA_UInt32)(pRates->OutputFileSize
5124 / M4MCS_MOOV_OVER_FILESIZE_RATIO
5125 / (pRates->OutputVideoBitrate
5126 + pRates->OutputAudioBitrate) * 8000.0);
5127
5128 if( maxduration + pRates->BeginCutTime
5129 > pC->InputFileProperties.uiClipDuration )
5130 {
5131 maxduration = pC->InputFileProperties.uiClipDuration
5132 - pRates->BeginCutTime;
5133 }
5134
5135 if( calcduration > maxduration )
5136 {
5137 calcduration = maxduration;
5138 }
5139
5140 if( calcduration == 0 )
5141 {
5142 return M4MCS_ERR_BEGIN_CUT_EQUALS_END_CUT;
5143 }
5144
5145 /* search max possible audio bitrate */
5146 maxcombinedbitrate = (M4OSA_UInt32)(pRates->OutputFileSize
5147 / M4MCS_MOOV_OVER_FILESIZE_RATIO
5148 / (calcduration / 8000.0));
5149
5150 while( ( fixed_audio == M4OSA_FALSE)
5151 && (pRates->OutputAudioBitrate
5152 < M4VIDEOEDITING_k96_KBPS) )
5153 {
5154 calcbitrate = M4MCS_intGetNearestBitrate(
5155 pRates->OutputAudioBitrate, +1);
5156
5157 if( calcbitrate
5158 + pRates->OutputVideoBitrate <= maxcombinedbitrate )
5159 pRates->OutputAudioBitrate = calcbitrate;
5160 else
5161 break;
5162 }
5163 }
5164 else
5165 {
5166 /* compute max duration */
5167 maxduration = (M4OSA_UInt32)(pRates->OutputFileSize
5168 / M4MCS_MOOV_OVER_FILESIZE_RATIO
5169 / (minvideobitrate + minaudiobitrate) * 8000.0);
5170
5171 if( maxduration + pRates->BeginCutTime
5172 > pC->InputFileProperties.uiClipDuration )
5173 {
5174 maxduration = pC->InputFileProperties.uiClipDuration
5175 - pRates->BeginCutTime;
5176 }
5177
5178 if( calcduration > maxduration )
5179 {
5180 calcduration = maxduration;
5181 }
5182
5183 if( calcduration == 0 )
5184 {
5185 return M4MCS_ERR_BEGIN_CUT_EQUALS_END_CUT;
5186 }
5187
5188 /* set audio = 1/3 and video = 2/3 */
5189 maxcombinedbitrate = (M4OSA_UInt32)(pRates->OutputFileSize
5190 / M4MCS_MOOV_OVER_FILESIZE_RATIO
5191 / (calcduration / 8000.0));
5192
5193 if( fixed_audio == M4OSA_FALSE )
5194 {
5195 if( pC->novideo )
5196 pRates->OutputAudioBitrate =
5197 M4MCS_intGetNearestBitrate(maxcombinedbitrate,
5198 0);
5199 else
5200 pRates->OutputAudioBitrate =
5201 M4MCS_intGetNearestBitrate(maxcombinedbitrate
5202 / 3, 0);
5203
5204 if( pRates->OutputAudioBitrate < minaudiobitrate )
5205 pRates->OutputAudioBitrate = minaudiobitrate;
5206
5207 if( pRates->OutputAudioBitrate
5208 > M4VIDEOEDITING_k96_KBPS )
5209 pRates->OutputAudioBitrate =
5210 M4VIDEOEDITING_k96_KBPS;
5211 }
5212
5213 if( fixed_video == M4OSA_FALSE )
5214 {
5215 pRates->OutputVideoBitrate =
5216 M4MCS_intGetNearestBitrate(maxcombinedbitrate
5217 - pRates->OutputAudioBitrate, 0);
5218
5219 if( pRates->OutputVideoBitrate < minvideobitrate )
5220 pRates->OutputVideoBitrate = minvideobitrate;
5221
5222 if( pRates->OutputVideoBitrate
5223 > M4VIDEOEDITING_k8_MBPS )
5224 pRates->OutputVideoBitrate =
5225 M4VIDEOEDITING_k8_MBPS; /*+ New Encoder
5226 bitrates */
5227 }
5228 }
5229 }
5230 }
5231 }
5232
5233 /* recompute max duration with final bitrates */
5234 if( pRates->OutputFileSize > 0 )
5235 {
5236 maxduration = (M4OSA_UInt32)(pRates->OutputFileSize
5237 / M4MCS_MOOV_OVER_FILESIZE_RATIO
5238 / (pRates->OutputVideoBitrate + pRates->OutputAudioBitrate)
5239 * 8000.0);
5240 }
5241 else
5242 {
5243 maxduration = pC->InputFileProperties.uiClipDuration;
5244 }
5245
5246 if( maxduration
5247 + pRates->BeginCutTime > pC->InputFileProperties.uiClipDuration )
5248 {
5249 maxduration =
5250 pC->InputFileProperties.uiClipDuration - pRates->BeginCutTime;
5251 }
5252
5253 if( pRates->EndCutTime == 0 )
5254 {
5255 pRates->EndCutTime = pRates->BeginCutTime + maxduration;
5256 }
5257 else
5258 {
5259 calcduration = pRates->EndCutTime - pRates->BeginCutTime;
5260
5261 if( calcduration > maxduration )
5262 {
5263 pRates->EndCutTime = pRates->BeginCutTime + maxduration;
5264 }
5265 }
5266
5267 /* Should never happen : constraints are too strong */
5268 if( pRates->EndCutTime == pRates->BeginCutTime )
5269 {
5270 return M4MCS_ERR_BEGIN_CUT_EQUALS_END_CUT;
5271 }
5272
5273 /* estimated resulting file size */
5274 pRates->OutputFileSize = (M4OSA_UInt32)(M4MCS_MOOV_OVER_FILESIZE_RATIO
5275 * (pRates->OutputVideoBitrate + pRates->OutputAudioBitrate)
5276 * (( pRates->EndCutTime - pRates->BeginCutTime) / 8000.0));
5277
5278 return M4NO_ERROR;
5279 }
5280
5281 /**
5282 ******************************************************************************
5283 * M4OSA_ERR M4MCS_checkParamsAndStart(M4MCS_Context pContext)
5284 * @brief Check parameters to start
5285 * @note
5286 * @param pContext (IN) MCS context
5287 * @return M4NO_ERROR: No error
5288 * @return M4ERR_PARAMETER: At least one parameter is M4OSA_NULL (debug only)
5289 * @return M4ERR_STATE: MCS is not in an appropriate state for
5290 * this function to be called
5291 * @return M4MCS_ERR_AUDIOBITRATE_TOO_HIGH:
5292 * Audio bitrate too high (we limit to 96 kbps)
5293 * @return M4MCS_ERR_AUDIOBITRATE_TOO_LOW:
5294 * Audio bitrate is too low (16 kbps min for aac,
5295 * 12.2 for amr, 8 for mp3)
5296 * @return M4MCS_ERR_BEGIN_CUT_EQUALS_END_CUT:
5297 * Begin cut and End cut are equals
5298 * @return M4MCS_ERR_BEGIN_CUT_LARGER_THAN_DURATION:
5299 * Begin cut time is larger than the input
5300 * clip duration
5301 * @return M4MCS_ERR_END_CUT_SMALLER_THAN_BEGIN_CUT:
5302 * End cut time is smaller than begin cut time
5303 * @return M4MCS_ERR_MAXFILESIZE_TOO_SMALL:
5304 * Not enough space to store whole output
5305 * file at given bitrates
5306 * @return M4MCS_ERR_VIDEOBITRATE_TOO_HIGH:
5307 * Video bitrate too high (we limit to 800 kbps)
5308 * @return M4MCS_ERR_VIDEOBITRATE_TOO_LOW:
5309 * Video bitrate too low
5310 ******************************************************************************
5311 */
M4MCS_checkParamsAndStart(M4MCS_Context pContext)5312 M4OSA_ERR M4MCS_checkParamsAndStart( M4MCS_Context pContext )
5313 {
5314 M4MCS_InternalContext *pC = (M4MCS_InternalContext *)(pContext);
5315 M4MCS_EncodingParams VerifyRates;
5316 M4OSA_ERR err;
5317
5318 /**
5319 * Check input parameters */
5320 M4OSA_DEBUG_IF2((M4OSA_NULL == pContext), M4ERR_PARAMETER,
5321 "M4MCS_checkParamsAndStart: pContext is M4OSA_NULL");
5322
5323 #ifdef M4MCS_SUPPORT_STILL_PICTURE
5324
5325 if( pC->m_bIsStillPicture )
5326 {
5327 /**
5328 * Call the corresponding still picture MCS function*/
5329 return M4MCS_stillPicCheckParamsAndStart(pC);
5330 }
5331
5332 #endif /*M4MCS_SUPPORT_STILL_PICTURE*/
5333
5334 /**
5335 * Check state automaton */
5336
5337 if( M4MCS_kState_SET != pC->State )
5338 {
5339 M4OSA_TRACE1_1(
5340 "M4MCS_checkParamsAndStart(): Wrong State (%d), returning M4ERR_STATE",
5341 pC->State);
5342 return M4ERR_STATE;
5343 }
5344
5345 /* Audio bitrate should not stay undefined at this point */
5346 if( ( pC->noaudio == M4OSA_FALSE)
5347 && (pC->AudioEncParams.Format != M4ENCODER_kAudioNULL)
5348 && (pC->uiAudioBitrate == M4VIDEOEDITING_kUndefinedBitrate) )
5349 {
5350 M4OSA_TRACE1_0("M4MCS_checkParamsAndStart : undefined audio bitrate");
5351 return M4MCS_ERR_AUDIOBITRATE_TOO_LOW;
5352 }
5353
5354 /* Video bitrate should not stay undefined at this point */
5355 if( ( pC->novideo == M4OSA_FALSE)
5356 && (pC->EncodingVideoFormat != M4ENCODER_kNULL)
5357 && (pC->uiVideoBitrate == M4VIDEOEDITING_kUndefinedBitrate) )
5358 {
5359 M4OSA_TRACE1_0("M4MCS_checkParamsAndStart : undefined video bitrate");
5360 return M4MCS_ERR_VIDEOBITRATE_TOO_LOW;
5361 }
5362
5363 /* Set end cut time if necessary (not an error) */
5364 if( pC->uiEndCutTime == 0 )
5365 {
5366 pC->uiEndCutTime = pC->InputFileProperties.uiClipDuration;
5367 }
5368
5369 /* Force a re-set to check validity of parameters */
5370 VerifyRates.OutputVideoBitrate = pC->uiVideoBitrate;
5371 VerifyRates.OutputAudioBitrate = pC->uiAudioBitrate;
5372 VerifyRates.BeginCutTime = pC->uiBeginCutTime;
5373 VerifyRates.EndCutTime = pC->uiEndCutTime;
5374 VerifyRates.OutputFileSize = pC->uiMaxFileSize;
5375 VerifyRates.OutputVideoTimescale = pC->outputVideoTimescale;
5376
5377 err = M4MCS_setEncodingParams(pContext, &VerifyRates);
5378
5379 /**
5380 * Check parameters consistency */
5381 if( err != M4NO_ERROR )
5382 {
5383 M4OSA_TRACE1_0("M4MCS_checkParamsAndStart : invalid parameter found");
5384 return err;
5385 }
5386
5387 /**
5388 * All is OK : update state automaton */
5389 pC->uiEncVideoBitrate = pC->uiVideoBitrate;
5390 pC->AudioEncParams.Bitrate = pC->uiAudioBitrate;
5391
5392 #ifdef M4MCS_WITH_FAST_OPEN
5393 /**
5394 * Remake the open if it was done in fast mode */
5395
5396 if( M4OSA_TRUE == pC->bFileOpenedInFastMode )
5397 {
5398 /* Close the file opened in fast mode */
5399 M4MCS_intCleanUp_ReadersDecoders(pC);
5400
5401 pC->State = M4MCS_kState_CREATED;
5402
5403 /* Reopen it in normal mode */
5404 err = M4MCS_open(pContext, pC->pInputFile, pC->InputFileType,
5405 pC->pOutputFile, pC->pTemporaryFile);
5406
5407 if( err != M4NO_ERROR )
5408 {
5409 M4OSA_TRACE1_1(
5410 "M4MCS_checkParamsAndStart : M4MCS_Open returns 0x%x", err);
5411 return err;
5412 }
5413 }
5414
5415 #endif /* M4MCS_WITH_FAST_OPEN */
5416
5417 pC->State = M4MCS_kState_READY;
5418
5419 return M4NO_ERROR;
5420 }
5421
5422 /**
5423 ******************************************************************************
5424 * M4OSA_ERR M4MCS_intStepSet(M4MCS_InternalContext* pC)
5425 ******************************************************************************
5426 */
M4MCS_intStepSet(M4MCS_InternalContext * pC)5427 static M4OSA_ERR M4MCS_intStepSet( M4MCS_InternalContext *pC )
5428 {
5429 M4OSA_ERR err;
5430 M4ENCODER_Header *encHeader;
5431
5432 /**
5433 * Prepare the video decoder */
5434 err = M4MCS_intPrepareVideoDecoder(pC);
5435
5436 if( M4NO_ERROR != err )
5437 {
5438 M4OSA_TRACE1_1(
5439 "M4MCS_intStepSet(): M4MCS_intPrepareVideoDecoder() returns 0x%x",
5440 err);
5441 return err;
5442 }
5443
5444 if( ( pC->InputFileProperties.VideoStreamType == M4VIDEOEDITING_kH264)
5445 && (pC->EncodingVideoFormat == M4ENCODER_kNULL) )
5446 {
5447 pC->bH264Trim = M4OSA_TRUE;
5448 }
5449
5450 /**
5451 * Prepare the video encoder */
5452 err = M4MCS_intPrepareVideoEncoder(pC);
5453
5454 if( M4NO_ERROR != err )
5455 {
5456 M4OSA_TRACE1_1(
5457 "M4MCS_intStepSet(): M4MCS_intPrepareVideoEncoder() returns 0x%x",
5458 err);
5459 return err;
5460 }
5461
5462 if( ( pC->uiBeginCutTime != 0)
5463 && (pC->InputFileProperties.VideoStreamType == M4VIDEOEDITING_kH264)
5464 && (pC->EncodingVideoFormat == M4ENCODER_kNULL) )
5465 {
5466
5467 err = pC->pVideoEncoderGlobalFcts->pFctSetOption(pC->pViEncCtxt,
5468 M4ENCODER_kOptionID_H264ProcessNALUContext,
5469 (M4OSA_DataOption)pC->m_pInstance);
5470
5471 if( err != M4NO_ERROR )
5472 {
5473 M4OSA_TRACE1_1("M4MCS_intStetSet :pFctSetOption failed (err 0x%x)",
5474 err);
5475 return err;
5476 }
5477
5478 err = pC->pVideoEncoderGlobalFcts->pFctSetOption(pC->pViEncCtxt,
5479 M4ENCODER_kOptionID_SetH264ProcessNALUfctsPtr,
5480 (M4OSA_DataOption) &H264MCS_ProcessEncodedNALU);
5481
5482 if( err != M4NO_ERROR )
5483 {
5484 M4OSA_TRACE1_1("M4MCS_intStetSet :pFctSetOption failed (err 0x%x)",
5485 err);
5486 return err;
5487 }
5488
5489 err = pC->pVideoEncoderGlobalFcts->pFctGetOption(pC->pViEncCtxt,
5490 M4ENCODER_kOptionID_EncoderHeader,
5491 (M4OSA_DataOption) &encHeader);
5492
5493 if( ( M4NO_ERROR != err) || (M4OSA_NULL == encHeader->pBuf) )
5494 {
5495 M4OSA_TRACE1_1(
5496 "M4MCS_close: failed to get the encoder header (err 0x%x)",
5497 err);
5498 /**< no return here, we still have stuff to deallocate after close, even if it fails.*/
5499 }
5500 else
5501 {
5502 // Handle DSI first bits
5503 #define SPS_START_POS 6
5504
5505 pC->m_pInstance->m_encoderSPSSize =
5506 ( encHeader->pBuf[SPS_START_POS] << 8)
5507 + encHeader->pBuf[SPS_START_POS + 1];
5508 pC->m_pInstance->m_pEncoderSPS =
5509 (M4OSA_UInt8 *)(encHeader->pBuf) + SPS_START_POS + 2;
5510
5511 pC->m_pInstance->m_encoderPPSSize =
5512 ( encHeader->pBuf[SPS_START_POS + 3
5513 + pC->m_pInstance->m_encoderSPSSize] << 8)
5514 + encHeader->pBuf[SPS_START_POS + 4
5515 + pC->m_pInstance->m_encoderSPSSize];
5516 pC->m_pInstance->m_pEncoderPPS = (M4OSA_UInt8 *)encHeader->pBuf + SPS_START_POS + 5
5517 + pC->m_pInstance->m_encoderSPSSize;
5518
5519 /* Check the DSI integrity */
5520 if( encHeader->Size != (pC->m_pInstance->m_encoderSPSSize
5521 + pC->m_pInstance->m_encoderPPSSize + 5 + SPS_START_POS) )
5522 {
5523 M4OSA_TRACE1_3(
5524 "!!! M4MCS_intStepSet ERROR : invalid SPS / PPS %d %d %d",
5525 encHeader->Size, pC->m_pInstance->m_encoderSPSSize,
5526 pC->m_pInstance->m_encoderPPSSize);
5527 return M4ERR_PARAMETER;
5528 }
5529 }
5530 }
5531
5532 /**
5533 * Prepare audio processing */
5534 err = M4MCS_intPrepareAudioProcessing(pC);
5535
5536 if( M4NO_ERROR != err )
5537 {
5538 M4OSA_TRACE1_1(
5539 "M4MCS_intStepSet(): M4MCS_intPrepareAudioProcessing() returns 0x%x",
5540 err);
5541 return err;
5542 }
5543
5544 /**
5545 * Prepare the writer */
5546 err = M4MCS_intPrepareWriter(pC);
5547
5548 if( M4NO_ERROR != err )
5549 {
5550 M4OSA_TRACE1_1(
5551 "M4MCS_intStepSet(): M4MCS_intPrepareWriter() returns 0x%x", err);
5552 return err;
5553 }
5554
5555 /**
5556 * Jump the audio stream to the begin cut time (all AUs are RAP)
5557 * Must be done after the 3gpp writer init, because it may write the first
5558 * audio AU in some cases */
5559 err = M4MCS_intPrepareAudioBeginCut(pC);
5560
5561 if( M4NO_ERROR != err )
5562 {
5563 M4OSA_TRACE1_1(
5564 "M4MCS_intStepSet(): M4MCS_intPrepareAudioBeginCut() returns 0x%x",
5565 err);
5566 return err;
5567 }
5568
5569 /**
5570 * Update state automaton */
5571 if( 0 == pC->uiBeginCutTime )
5572 {
5573 pC->dViDecStartingCts = 0.0;
5574 /**
5575 * No begin cut, do the encoding */
5576 pC->State = M4MCS_kState_PROCESSING;
5577 }
5578 else
5579 {
5580 /**
5581 * Remember that we must start the decode/encode process at the begin cut time */
5582 pC->dViDecStartingCts = (M4OSA_Double)pC->uiBeginCutTime;
5583
5584 /**
5585 * Jumping */
5586 pC->State = M4MCS_kState_BEGINVIDEOJUMP;
5587 }
5588
5589 /**
5590 * Return with no error */
5591 M4OSA_TRACE3_0("M4MCS_intStepSet(): returning M4NO_ERROR");
5592 return M4NO_ERROR;
5593 }
5594
5595 /**
5596 ******************************************************************************
5597 * M4OSA_ERR M4MCS_intPrepareVideoDecoder(M4MCS_InternalContext* pC);
5598 * @brief Prepare the video decoder.
5599 * @param pC (IN) MCS private context
5600 * @return M4NO_ERROR No error
5601 * @return M4MCS_ERR_H263_PROFILE_NOT_SUPPORTED
5602 * @return Any error returned by an underlaying module
5603 ******************************************************************************
5604 */
M4MCS_intPrepareVideoDecoder(M4MCS_InternalContext * pC)5605 static M4OSA_ERR M4MCS_intPrepareVideoDecoder( M4MCS_InternalContext *pC )
5606 {
5607 M4OSA_ERR err;
5608 M4OSA_Void *decoderUserData;
5609 M4DECODER_OutputFilter FilterOption;
5610
5611 if( pC->novideo )
5612 return M4NO_ERROR;
5613
5614 /**
5615 * Create the decoder, if it has not been created yet (to get video properties for example) */
5616 if( M4OSA_NULL == pC->pViDecCtxt )
5617 {
5618 #ifdef M4VSS_ENABLE_EXTERNAL_DECODERS
5619
5620 decoderUserData = pC->m_pCurrentVideoDecoderUserData;
5621
5622 #else
5623
5624 decoderUserData = M4OSA_NULL;
5625
5626 #endif /* M4VSS_ENABLE_EXTERNAL_DECODERS ? */
5627
5628 err = pC->m_pVideoDecoder->m_pFctCreate(&pC->pViDecCtxt,
5629 &pC->pReaderVideoStream->m_basicProperties, pC->m_pReader,
5630 pC->m_pReaderDataIt, &pC->ReaderVideoAU, decoderUserData);
5631
5632 if( (M4OSA_UInt32)(M4ERR_DECODER_H263_PROFILE_NOT_SUPPORTED) == err )
5633 {
5634 /**
5635 * Our decoder is not compatible with H263 profile other than 0.
5636 * So it returns this internal error code.
5637 * We translate it to our own error code */
5638 M4OSA_TRACE1_0("M4MCS_intPrepareVideoDecoder:\
5639 returning M4MCS_ERR_H263_PROFILE_NOT_SUPPORTED");
5640 return M4MCS_ERR_H263_PROFILE_NOT_SUPPORTED;
5641 }
5642 else if( M4NO_ERROR != err )
5643 {
5644 M4OSA_TRACE1_1("M4MCS_intPrepareVideoDecoder:\
5645 m_pVideoDecoder->m_pFctCreate returns 0x%x", err);
5646 return err;
5647 }
5648
5649 if( M4VIDEOEDITING_kH264 == pC->InputFileProperties.VideoStreamType )
5650 {
5651 FilterOption.m_pFilterFunction =
5652 (M4OSA_Void *) &M4VIFI_ResizeBilinearYUV420toYUV420;
5653 FilterOption.m_pFilterUserData = M4OSA_NULL;
5654 err = pC->m_pVideoDecoder->m_pFctSetOption(pC->pViDecCtxt,
5655 M4DECODER_kOptionID_OutputFilter,
5656 (M4OSA_DataOption) &FilterOption);
5657
5658 if( M4NO_ERROR != err )
5659 {
5660 M4OSA_TRACE1_1("M4MCS_intPrepareVideoDecoder:\
5661 m_pVideoDecoder->m_pFctSetOption returns 0x%x", err);
5662 return err;
5663 }
5664 }
5665 }
5666
5667 /**
5668 * Return with no error */
5669 M4OSA_TRACE3_0("M4MCS_intPrepareVideoDecoder(): returning M4NO_ERROR");
5670 return M4NO_ERROR;
5671 }
5672
5673 /**
5674 ******************************************************************************
5675 * M4OSA_ERR M4MCS_intPrepareVideoEncoder(M4MCS_InternalContext* pC);
5676 * @brief Prepare the video encoder.
5677 * @param pC (IN) MCS private context
5678 * @return M4NO_ERROR No error
5679 * @return Any error returned by an underlaying module
5680 ******************************************************************************
5681 */
M4MCS_intPrepareVideoEncoder(M4MCS_InternalContext * pC)5682 static M4OSA_ERR M4MCS_intPrepareVideoEncoder( M4MCS_InternalContext *pC )
5683 {
5684 M4OSA_ERR err;
5685 M4ENCODER_AdvancedParams EncParams; /**< Encoder advanced parameters */
5686 M4ENCODER_Params EncParams1;
5687 M4OSA_Double dFrameRate; /**< tmp variable */
5688
5689 if( pC->novideo )
5690 return M4NO_ERROR;
5691
5692 if( pC->EncodingVideoFormat == M4ENCODER_kNULL )
5693 {
5694 /* Approximative cts increment */
5695 pC->dCtsIncrement = 1000.0 / pC->pReaderVideoStream->m_averageFrameRate;
5696
5697 if( pC->uiBeginCutTime == 0 )
5698 {
5699 M4OSA_TRACE3_0(
5700 "M4MCS_intPrepareVideoEncoder(): Null encoding, do nothing.");
5701 return M4NO_ERROR;
5702 }
5703 else
5704 {
5705 M4OSA_TRACE3_0(
5706 "M4MCS_intPrepareVideoEncoder(): Null encoding, I-frame defaults.");
5707
5708 /* Set useful parameters to encode the first I-frame */
5709 EncParams.InputFormat = M4ENCODER_kIYUV420;
5710 EncParams.videoProfile = pC->encodingVideoProfile;
5711 EncParams.videoLevel= pC->encodingVideoLevel;
5712
5713 switch( pC->InputFileProperties.VideoStreamType )
5714 {
5715 case M4VIDEOEDITING_kH263:
5716 EncParams.Format = M4ENCODER_kH263;
5717 break;
5718
5719 case M4VIDEOEDITING_kMPEG4:
5720 EncParams.Format = M4ENCODER_kMPEG4;
5721 break;
5722
5723 case M4VIDEOEDITING_kH264:
5724 EncParams.Format = M4ENCODER_kH264;
5725 break;
5726
5727 default:
5728 M4OSA_TRACE1_1("M4MCS_intPrepareVideoEncoder: unknown encoding video format\
5729 (%d), returning M4MCS_WAR_MEDIATYPE_NOT_SUPPORTED",
5730 pC->InputFileProperties.VideoStreamType);
5731 return M4MCS_WAR_MEDIATYPE_NOT_SUPPORTED;
5732 }
5733
5734 EncParams.FrameWidth = pC->EncodingWidth;
5735 EncParams.FrameHeight = pC->EncodingHeight;
5736 EncParams.Bitrate = pC->uiEncVideoBitrate;
5737 EncParams.bInternalRegulation =
5738 M4OSA_FALSE; /* do not constrain the I-frame */
5739 EncParams.FrameRate = pC->EncodingVideoFramerate;
5740
5741 /* Other encoding settings (quite all dummy...) */
5742 EncParams.uiHorizontalSearchRange = 0; /* use default */
5743 EncParams.uiVerticalSearchRange = 0; /* use default */
5744 EncParams.bErrorResilience = M4OSA_FALSE; /* no error resilience */
5745 EncParams.uiIVopPeriod = 0; /* use default */
5746 EncParams.uiMotionEstimationTools =
5747 0; /* M4V_MOTION_EST_TOOLS_ALL */
5748 EncParams.bAcPrediction = M4OSA_TRUE; /* use AC prediction */
5749 EncParams.uiStartingQuantizerValue = 5; /* initial QP = 5 */
5750 EncParams.bDataPartitioning =
5751 M4OSA_FALSE; /* no data partitioning */
5752
5753 /* Rate factor */
5754 EncParams.uiTimeScale = pC->InputFileProperties.uiVideoTimeScale;
5755 EncParams.uiRateFactor = 1;
5756 }
5757 }
5758 else
5759 {
5760 M4OSA_TRACE3_0(
5761 "M4MCS_intPrepareVideoEncoder(): Normal encoding, set full config.");
5762
5763 /**
5764 * Set encoder shell parameters according to MCS settings */
5765 EncParams.Format = pC->EncodingVideoFormat;
5766 EncParams.InputFormat = M4ENCODER_kIYUV420;
5767 EncParams.videoProfile = pC->encodingVideoProfile;
5768 EncParams.videoLevel= pC->encodingVideoLevel;
5769
5770 /**
5771 * Video frame size */
5772 EncParams.FrameWidth = pC->EncodingWidth;
5773 EncParams.FrameHeight = pC->EncodingHeight;
5774
5775 /**
5776 * Video bitrate has been previously computed */
5777 EncParams.Bitrate = pC->uiEncVideoBitrate;
5778
5779 /**
5780 * MCS use the "true" core internal bitrate regulation */
5781 EncParams.bInternalRegulation = M4OSA_TRUE;
5782
5783 /**
5784 * Other encoder settings */
5785
5786 EncParams.uiHorizontalSearchRange = 0; /* use default */
5787 EncParams.uiVerticalSearchRange = 0; /* use default */
5788 EncParams.bErrorResilience = M4OSA_FALSE; /* no error resilience */
5789 EncParams.uiIVopPeriod = 0; /* use default */
5790 EncParams.uiMotionEstimationTools =
5791 0; /* M4V_MOTION_EST_TOOLS_ALL */
5792 EncParams.bAcPrediction = M4OSA_TRUE; /* use AC prediction */
5793 EncParams.uiStartingQuantizerValue = 10; /* initial QP = 10 */
5794 EncParams.bDataPartitioning =
5795 M4OSA_FALSE; /* no data partitioning */
5796
5797
5798 /**
5799 * Video encoder frame rate and rate factor */
5800 EncParams.FrameRate = pC->EncodingVideoFramerate;
5801 EncParams.uiTimeScale = pC->outputVideoTimescale;
5802
5803 switch( pC->EncodingVideoFramerate )
5804 {
5805 case M4ENCODER_k5_FPS:
5806 dFrameRate = 5.0;
5807 break;
5808
5809 case M4ENCODER_k7_5_FPS:
5810 dFrameRate = 7.5;
5811 break;
5812
5813 case M4ENCODER_k10_FPS:
5814 dFrameRate = 10.0;
5815 break;
5816
5817 case M4ENCODER_k12_5_FPS:
5818 dFrameRate = 12.5;
5819 break;
5820
5821 case M4ENCODER_k15_FPS:
5822 dFrameRate = 15.0;
5823 break;
5824
5825 case M4ENCODER_k20_FPS: /**< MPEG-4 only */
5826 dFrameRate = 20.0;
5827 break;
5828
5829 case M4ENCODER_k25_FPS: /**< MPEG-4 only */
5830 dFrameRate = 25.0;
5831 break;
5832
5833 case M4ENCODER_k30_FPS:
5834 dFrameRate = 30.0;
5835 break;
5836
5837 default:
5838 M4OSA_TRACE1_1(
5839 "M4MCS_intPrepareVideoEncoder: unknown encoding video frame rate\
5840 (0x%x), returning M4MCS_ERR_UNDEFINED_OUTPUT_VIDEO_FRAME_RATE",
5841 pC->EncodingVideoFramerate);
5842 return M4MCS_ERR_UNDEFINED_OUTPUT_VIDEO_FRAME_RATE;
5843 }
5844
5845 /**
5846 * Compute the number of milliseconds between two frames */
5847 if( M4ENCODER_kH263 == EncParams.Format )
5848 {
5849 pC->dCtsIncrement = 1001.0 / dFrameRate;
5850 }
5851 else /**< MPEG4 or H.264 */
5852 {
5853 pC->dCtsIncrement = 1000.0 / dFrameRate;
5854 }
5855 }
5856
5857 /**
5858 * Limit the video bitrate according to encoder profile
5859 * and level */
5860 err = M4MCS_intLimitBitratePerCodecProfileLevel(&EncParams);
5861 if (M4NO_ERROR != err) {
5862 M4OSA_TRACE1_1(
5863 "M4MCS_intPrepareVideoEncoder: limit bitrate returned err \
5864 0x%x", err);
5865 return err;
5866 }
5867
5868 /**
5869 * Create video encoder */
5870 err = pC->pVideoEncoderGlobalFcts->pFctInit(&pC->pViEncCtxt,
5871 pC->pWriterDataFcts, \
5872 M4MCS_intApplyVPP, pC, pC->pCurrentVideoEncoderExternalAPI, \
5873 pC->pCurrentVideoEncoderUserData);
5874
5875 /**< We put the MCS context in place of the VPP context */
5876 if( M4NO_ERROR != err )
5877 {
5878 M4OSA_TRACE1_1(
5879 "M4MCS_intPrepareVideoEncoder: EncoderInt->pFctInit returns 0x%x",
5880 err);
5881 return err;
5882 }
5883
5884 pC->encoderState = M4MCS_kEncoderClosed;
5885
5886 if( M4OSA_TRUE == pC->bH264Trim )
5887 //if((M4ENCODER_kNULL == pC->EncodingVideoFormat)
5888 // && (M4VIDEOEDITING_kH264 == pC->InputFileProperties.VideoStreamType))
5889 {
5890 EncParams1.InputFormat = EncParams.InputFormat;
5891 //EncParams1.InputFrameWidth = EncParams.InputFrameWidth;
5892 //EncParams1.InputFrameHeight = EncParams.InputFrameHeight;
5893 EncParams1.FrameWidth = EncParams.FrameWidth;
5894 EncParams1.FrameHeight = EncParams.FrameHeight;
5895 EncParams1.videoProfile= EncParams.videoProfile;
5896 EncParams1.videoLevel= EncParams.videoLevel;
5897 EncParams1.Bitrate = EncParams.Bitrate;
5898 EncParams1.FrameRate = EncParams.FrameRate;
5899 EncParams1.Format = M4ENCODER_kH264; //EncParams.Format;
5900 M4OSA_TRACE1_2("mcs encoder open profile :%d, level %d",
5901 EncParams1.videoProfile, EncParams1.videoLevel);
5902 err = pC->pVideoEncoderGlobalFcts->pFctOpen(pC->pViEncCtxt,
5903 &pC->WriterVideoAU, &EncParams1);
5904 }
5905 else
5906 {
5907 M4OSA_TRACE1_2("mcs encoder open Adv profile :%d, level %d",
5908 EncParams.videoProfile, EncParams.videoLevel);
5909 err = pC->pVideoEncoderGlobalFcts->pFctOpen(pC->pViEncCtxt,
5910 &pC->WriterVideoAU, &EncParams);
5911 }
5912
5913 if( M4NO_ERROR != err )
5914 {
5915 M4OSA_TRACE1_1(
5916 "M4MCS_intPrepareVideoEncoder: EncoderInt->pFctOpen returns 0x%x",
5917 err);
5918 return err;
5919 }
5920
5921 pC->encoderState = M4MCS_kEncoderStopped;
5922
5923 if( M4OSA_NULL != pC->pVideoEncoderGlobalFcts->pFctStart )
5924 {
5925 err = pC->pVideoEncoderGlobalFcts->pFctStart(pC->pViEncCtxt);
5926
5927 if( M4NO_ERROR != err )
5928 {
5929 M4OSA_TRACE1_1(
5930 "M4MCS_intPrepareVideoEncoder: EncoderInt->pFctStart returns 0x%x",
5931 err);
5932 return err;
5933 }
5934 }
5935
5936 pC->encoderState = M4MCS_kEncoderRunning;
5937
5938 /******************************/
5939 /* Video resize management */
5940 /******************************/
5941 /**
5942 * Compare video input size and video output size to check if resize is needed */
5943 if( ( (M4OSA_UInt32)EncParams.FrameWidth
5944 != pC->pReaderVideoStream->m_videoWidth)
5945 || ((M4OSA_UInt32)EncParams.FrameHeight
5946 != pC->pReaderVideoStream->m_videoHeight) )
5947 {
5948 /**
5949 * Allocate the intermediate video plane that will receive the decoded image before
5950 resizing */
5951 pC->pPreResizeFrame =
5952 (M4VIFI_ImagePlane *)M4OSA_32bitAlignedMalloc(3 * sizeof(M4VIFI_ImagePlane),
5953 M4MCS, (M4OSA_Char *)"m_pPreResizeFrame");
5954
5955 if( M4OSA_NULL == pC->pPreResizeFrame )
5956 {
5957 M4OSA_TRACE1_0("M4MCS_intPrepareVideoEncoder():\
5958 unable to allocate m_pPreResizeFrame, returning M4ERR_ALLOC");
5959 return M4ERR_ALLOC;
5960 }
5961
5962 pC->pPreResizeFrame[0].pac_data = M4OSA_NULL;
5963 pC->pPreResizeFrame[1].pac_data = M4OSA_NULL;
5964 pC->pPreResizeFrame[2].pac_data = M4OSA_NULL;
5965
5966 /**
5967 * Allocate the Y plane */
5968 pC->pPreResizeFrame[0].u_topleft = 0;
5969 pC->pPreResizeFrame[0].u_width = pC->pReaderVideoStream->
5970 m_videoWidth; /**< input width */
5971 pC->pPreResizeFrame[0].u_height = pC->pReaderVideoStream->
5972 m_videoHeight; /**< input height */
5973 pC->pPreResizeFrame[0].u_stride = pC->
5974 pPreResizeFrame[0].u_width; /**< simple case: stride equals width */
5975
5976 pC->pPreResizeFrame[0].pac_data =
5977 (M4VIFI_UInt8 *)M4OSA_32bitAlignedMalloc(pC->pPreResizeFrame[0].u_stride \
5978 *pC->pPreResizeFrame[0].u_height, M4MCS,
5979 (M4OSA_Char *)"m_pPreResizeFrame[0].pac_data");
5980
5981 if( M4OSA_NULL == pC->pPreResizeFrame[0].pac_data )
5982 {
5983 M4OSA_TRACE1_0(
5984 "M4MCS_intPrepareVideoEncoder():\
5985 unable to allocate m_pPreResizeFrame[0].pac_data, returning M4ERR_ALLOC");
5986 return M4ERR_ALLOC;
5987 }
5988
5989 /**
5990 * Allocate the U plane */
5991 pC->pPreResizeFrame[1].u_topleft = 0;
5992 pC->pPreResizeFrame[1].u_width = pC->pPreResizeFrame[0].u_width
5993 >> 1; /**< U width is half the Y width */
5994 pC->pPreResizeFrame[1].u_height = pC->pPreResizeFrame[0].u_height
5995 >> 1; /**< U height is half the Y height */
5996 pC->pPreResizeFrame[1].u_stride = pC->
5997 pPreResizeFrame[1].u_width; /**< simple case: stride equals width */
5998
5999 pC->pPreResizeFrame[1].pac_data =
6000 (M4VIFI_UInt8 *)M4OSA_32bitAlignedMalloc(pC->pPreResizeFrame[1].u_stride \
6001 *pC->pPreResizeFrame[1].u_height, M4MCS,
6002 (M4OSA_Char *)"m_pPreResizeFrame[1].pac_data");
6003
6004 if( M4OSA_NULL == pC->pPreResizeFrame[1].pac_data )
6005 {
6006 M4OSA_TRACE1_0(
6007 "M4MCS_intPrepareVideoEncoder():\
6008 unable to allocate m_pPreResizeFrame[1].pac_data, returning M4ERR_ALLOC");
6009 return M4ERR_ALLOC;
6010 }
6011
6012 /**
6013 * Allocate the V plane */
6014 pC->pPreResizeFrame[2].u_topleft = 0;
6015 pC->pPreResizeFrame[2].u_width = pC->
6016 pPreResizeFrame[1].u_width; /**< V width equals U width */
6017 pC->pPreResizeFrame[2].u_height = pC->
6018 pPreResizeFrame[1].u_height; /**< V height equals U height */
6019 pC->pPreResizeFrame[2].u_stride = pC->
6020 pPreResizeFrame[2].u_width; /**< simple case: stride equals width */
6021
6022 pC->pPreResizeFrame[2].pac_data =
6023 (M4VIFI_UInt8 *)M4OSA_32bitAlignedMalloc(pC->pPreResizeFrame[2].u_stride \
6024 *pC->pPreResizeFrame[2].u_height, M4MCS,
6025 (M4OSA_Char *)"m_pPreResizeFrame[1].pac_data");
6026
6027 if( M4OSA_NULL == pC->pPreResizeFrame[2].pac_data )
6028 {
6029 M4OSA_TRACE1_0(
6030 "M4MCS_intPrepareVideoEncoder():\
6031 unable to allocate m_pPreResizeFrame[2].pac_data, returning M4ERR_ALLOC");
6032 return M4ERR_ALLOC;
6033 }
6034 }
6035
6036 /**
6037 * Return with no error */
6038 M4OSA_TRACE3_0("M4MCS_intPrepareVideoEncoder(): returning M4NO_ERROR");
6039 return M4NO_ERROR;
6040 }
6041
6042 /**
6043 ******************************************************************************
6044 * M4OSA_ERR M4MCS_intPrepareAudioProcessing(M4MCS_InternalContext* pC);
6045 * @brief Prepare the AAC decoder, the SRC and the AMR-NB encoder and the MP3 encoder.
6046 * @param pC (IN) MCS private context
6047 * @return M4NO_ERROR No error
6048 * @return Any error returned by an underlaying module
6049 ******************************************************************************
6050 */
M4MCS_intPrepareAudioProcessing(M4MCS_InternalContext * pC)6051 static M4OSA_ERR M4MCS_intPrepareAudioProcessing( M4MCS_InternalContext *pC )
6052 {
6053 M4OSA_ERR err;
6054
6055 SSRC_ReturnStatus_en
6056 ReturnStatus; /* Function return status */
6057 LVM_INT16 NrSamplesMin =
6058 0; /* Minimal number of samples on the input or on the output */
6059 LVM_INT32 ScratchSize; /* The size of the scratch memory */
6060 LVM_INT16
6061 *pInputInScratch; /* Pointer to input in the scratch buffer */
6062 LVM_INT16
6063 *pOutputInScratch; /* Pointer to the output in the scratch buffer */
6064 SSRC_Params_t ssrcParams; /* Memory for init parameters */
6065
6066 #ifdef MCS_DUMP_PCM_TO_FILE
6067
6068 file_au_reader = fopen("mcs_ReaderOutput.raw", "wb");
6069 file_pcm_decoder = fopen("mcs_DecoderOutput.pcm", "wb");
6070 file_pcm_encoder = fopen("mcs_EncoderInput.pcm", "wb");
6071
6072 #endif
6073
6074 if( pC->noaudio )
6075 return M4NO_ERROR;
6076
6077 if( pC->AudioEncParams.Format == M4ENCODER_kAudioNULL )
6078 {
6079 M4OSA_TRACE3_0(
6080 "M4MCS_intPrepareAudioProcessing(): Null encoding, do nothing.");
6081 return M4NO_ERROR;
6082 }
6083
6084 /* ________________________________ */
6085 /*| |*/
6086 /*| Create and "start" the decoder |*/
6087 /*|________________________________|*/
6088
6089 if( M4OSA_NULL == pC->m_pAudioDecoder )
6090 {
6091 M4OSA_TRACE1_0(
6092 "M4MCS_intPrepareAudioProcessing(): Fails to initiate the audio decoder.");
6093 return M4MCS_ERR_AUDIO_CONVERSION_FAILED;
6094 }
6095
6096 if( M4OSA_NULL == pC->pAudioDecCtxt )
6097 {
6098 err = pC->m_pAudioDecoder->m_pFctCreateAudioDec(&pC->pAudioDecCtxt,
6099 pC->pReaderAudioStream, pC->m_pCurrentAudioDecoderUserData);
6100
6101 if( M4NO_ERROR != err )
6102 {
6103 M4OSA_TRACE1_1(
6104 "M4MCS_intPrepareVideoDecoder: m_pAudioDecoder->m_pFctCreateAudioDec returns 0x%x",
6105 err);
6106 return err;
6107 }
6108 }
6109
6110 if( M4VIDEOEDITING_kAMR_NB == pC->InputFileProperties.AudioStreamType ) {
6111 /* AMR DECODER CONFIGURATION */
6112
6113 /* nothing specific to do */
6114 }
6115 else if( M4VIDEOEDITING_kEVRC == pC->InputFileProperties.AudioStreamType ) {
6116 /* EVRC DECODER CONFIGURATION */
6117
6118 /* nothing specific to do */
6119 }
6120 else if( M4VIDEOEDITING_kMP3 == pC->InputFileProperties.AudioStreamType ) {
6121 /* MP3 DECODER CONFIGURATION */
6122
6123 /* nothing specific to do */
6124 }
6125 else
6126 {
6127 /* AAC DECODER CONFIGURATION */
6128 M4_AacDecoderConfig AacDecParam;
6129
6130 AacDecParam.m_AACDecoderProfile = AAC_kAAC;
6131 AacDecParam.m_DownSamplingMode = AAC_kDS_OFF;
6132
6133 if( pC->AudioEncParams.Format == M4ENCODER_kAMRNB )
6134 {
6135 AacDecParam.m_OutputMode = AAC_kMono;
6136 }
6137 else
6138 {
6139 /* For this version, we encode only in AAC */
6140 if( M4ENCODER_kMono == pC->AudioEncParams.ChannelNum )
6141 {
6142 AacDecParam.m_OutputMode = AAC_kMono;
6143 }
6144 else
6145 {
6146 AacDecParam.m_OutputMode = AAC_kStereo;
6147 }
6148 }
6149
6150 pC->m_pAudioDecoder->m_pFctSetOptionAudioDec(pC->pAudioDecCtxt,
6151 M4AD_kOptionID_UserParam, (M4OSA_DataOption) &AacDecParam);
6152 }
6153
6154 pC->m_pAudioDecoder->m_pFctSetOptionAudioDec(pC->pAudioDecCtxt,
6155 M4AD_kOptionID_3gpReaderInterface, (M4OSA_DataOption) pC->m_pReaderDataIt);
6156
6157 pC->m_pAudioDecoder->m_pFctSetOptionAudioDec(pC->pAudioDecCtxt,
6158 M4AD_kOptionID_AudioAU, (M4OSA_DataOption) &pC->ReaderAudioAU);
6159
6160 if( pC->m_pAudioDecoder->m_pFctStartAudioDec != M4OSA_NULL )
6161 {
6162 /* Not implemented in all decoders */
6163 err = pC->m_pAudioDecoder->m_pFctStartAudioDec(pC->pAudioDecCtxt);
6164
6165 if( M4NO_ERROR != err )
6166 {
6167 M4OSA_TRACE1_1(
6168 "M4MCS_intPrepareVideoDecoder: m_pAudioDecoder->m_pFctStartAudioDec returns 0x%x",
6169 err);
6170 return err;
6171 }
6172 }
6173
6174 /**
6175 * Allocate output buffer for the audio decoder */
6176 pC->InputFileProperties.uiDecodedPcmSize =
6177 pC->pReaderAudioStream->m_byteFrameLength
6178 * pC->pReaderAudioStream->m_byteSampleSize
6179 * pC->pReaderAudioStream->m_nbChannels;
6180
6181 if( pC->InputFileProperties.uiDecodedPcmSize > 0 )
6182 {
6183 pC->AudioDecBufferOut.m_bufferSize =
6184 pC->InputFileProperties.uiDecodedPcmSize;
6185 pC->AudioDecBufferOut.m_dataAddress =
6186 (M4OSA_MemAddr8)M4OSA_32bitAlignedMalloc(pC->AudioDecBufferOut.m_bufferSize \
6187 *sizeof(short), M4MCS, (M4OSA_Char *)"AudioDecBufferOut.m_bufferSize");
6188 }
6189
6190 if( M4OSA_NULL == pC->AudioDecBufferOut.m_dataAddress )
6191 {
6192 M4OSA_TRACE1_0(
6193 "M4MCS_intPrepareVideoDecoder():\
6194 unable to allocate AudioDecBufferOut.m_dataAddress, returning M4ERR_ALLOC");
6195 return M4ERR_ALLOC;
6196 }
6197
6198 /* _________________________ */
6199 /*| |*/
6200 /*| Set the SSRC parameters |*/
6201 /*|_________________________|*/
6202
6203 switch( pC->pReaderAudioStream->m_samplingFrequency )
6204 {
6205 case 8000:
6206 ssrcParams.SSRC_Fs_In = LVM_FS_8000;
6207 break;
6208
6209 case 11025:
6210 ssrcParams.SSRC_Fs_In = LVM_FS_11025;
6211 break;
6212
6213 case 12000:
6214 ssrcParams.SSRC_Fs_In = LVM_FS_12000;
6215 break;
6216
6217 case 16000:
6218 ssrcParams.SSRC_Fs_In = LVM_FS_16000;
6219 break;
6220
6221 case 22050:
6222 ssrcParams.SSRC_Fs_In = LVM_FS_22050;
6223 break;
6224
6225 case 24000:
6226 ssrcParams.SSRC_Fs_In = LVM_FS_24000;
6227 break;
6228
6229 case 32000:
6230 ssrcParams.SSRC_Fs_In = LVM_FS_32000;
6231 break;
6232
6233 case 44100:
6234 ssrcParams.SSRC_Fs_In = LVM_FS_44100;
6235 break;
6236
6237 case 48000:
6238 ssrcParams.SSRC_Fs_In = LVM_FS_48000;
6239 break;
6240
6241 default:
6242 M4OSA_TRACE1_1(
6243 "M4MCS_intPrepareVideoDecoder: invalid input AAC sampling frequency (%d Hz),\
6244 returning M4MCS_ERR_INVALID_AAC_SAMPLING_FREQUENCY",
6245 pC->pReaderAudioStream->m_samplingFrequency);
6246 return M4MCS_ERR_INVALID_AAC_SAMPLING_FREQUENCY;
6247 }
6248
6249 if( 1 == pC->pReaderAudioStream->m_nbChannels )
6250 {
6251 ssrcParams.SSRC_NrOfChannels = LVM_MONO;
6252 }
6253 else
6254 {
6255 ssrcParams.SSRC_NrOfChannels = LVM_STEREO;
6256 }
6257
6258 /*FlB 26.02.2009: add mp3 as output format*/
6259 if( pC->AudioEncParams.Format == M4ENCODER_kAAC
6260 || pC->AudioEncParams.Format == M4ENCODER_kMP3 )
6261 {
6262 switch( pC->AudioEncParams.Frequency )
6263 {
6264 case M4ENCODER_k8000Hz:
6265 ssrcParams.SSRC_Fs_Out = LVM_FS_8000;
6266 break;
6267
6268 case M4ENCODER_k11025Hz:
6269 ssrcParams.SSRC_Fs_Out = LVM_FS_11025;
6270 break;
6271
6272 case M4ENCODER_k12000Hz:
6273 ssrcParams.SSRC_Fs_Out = LVM_FS_12000;
6274 break;
6275
6276 case M4ENCODER_k16000Hz:
6277 ssrcParams.SSRC_Fs_Out = LVM_FS_16000;
6278 break;
6279
6280 case M4ENCODER_k22050Hz:
6281 ssrcParams.SSRC_Fs_Out = LVM_FS_22050;
6282 break;
6283
6284 case M4ENCODER_k24000Hz:
6285 ssrcParams.SSRC_Fs_Out = LVM_FS_24000;
6286 break;
6287
6288 case M4ENCODER_k32000Hz:
6289 ssrcParams.SSRC_Fs_Out = LVM_FS_32000;
6290 break;
6291
6292 case M4ENCODER_k44100Hz:
6293 ssrcParams.SSRC_Fs_Out = LVM_FS_44100;
6294 break;
6295
6296 case M4ENCODER_k48000Hz:
6297 ssrcParams.SSRC_Fs_Out = LVM_FS_48000;
6298 break;
6299
6300 default:
6301 M4OSA_TRACE1_1(
6302 "M4MCS_intPrepareAudioProcessing: invalid output AAC sampling frequency \
6303 (%d Hz), returning M4MCS_ERR_INVALID_AAC_SAMPLING_FREQUENCY",
6304 pC->AudioEncParams.Frequency);
6305 return M4MCS_ERR_INVALID_AAC_SAMPLING_FREQUENCY;
6306 break;
6307 }
6308 }
6309 else
6310 {
6311 ssrcParams.SSRC_Fs_Out = LVM_FS_8000;
6312 }
6313
6314
6315
6316 ReturnStatus = 0;
6317
6318 switch( ssrcParams.SSRC_Fs_In )
6319 {
6320 case LVM_FS_8000:
6321 ssrcParams.NrSamplesIn = 320;
6322 break;
6323
6324 case LVM_FS_11025:
6325 ssrcParams.NrSamplesIn = 441;
6326 break;
6327
6328 case LVM_FS_12000:
6329 ssrcParams.NrSamplesIn = 480;
6330 break;
6331
6332 case LVM_FS_16000:
6333 ssrcParams.NrSamplesIn = 640;
6334 break;
6335
6336 case LVM_FS_22050:
6337 ssrcParams.NrSamplesIn = 882;
6338 break;
6339
6340 case LVM_FS_24000:
6341 ssrcParams.NrSamplesIn = 960;
6342 break;
6343
6344 case LVM_FS_32000:
6345 ssrcParams.NrSamplesIn = 1280;
6346 break;
6347
6348 case LVM_FS_44100:
6349 ssrcParams.NrSamplesIn = 1764;
6350 break;
6351
6352 case LVM_FS_48000:
6353 ssrcParams.NrSamplesIn = 1920;
6354 break;
6355
6356 default:
6357 ReturnStatus = -1;
6358 break;
6359 }
6360
6361 switch( ssrcParams.SSRC_Fs_Out )
6362 {
6363 case LVM_FS_8000:
6364 ssrcParams.NrSamplesOut = 320;
6365 break;
6366
6367 case LVM_FS_11025:
6368 ssrcParams.NrSamplesOut = 441;
6369 break;
6370
6371 case LVM_FS_12000:
6372 ssrcParams.NrSamplesOut = 480;
6373 break;
6374
6375 case LVM_FS_16000:
6376 ssrcParams.NrSamplesOut = 640;
6377 break;
6378
6379 case LVM_FS_22050:
6380 ssrcParams.NrSamplesOut = 882;
6381 break;
6382
6383 case LVM_FS_24000:
6384 ssrcParams.NrSamplesOut = 960;
6385 break;
6386
6387 case LVM_FS_32000:
6388 ssrcParams.NrSamplesOut = 1280;
6389 break;
6390
6391 case LVM_FS_44100:
6392 ssrcParams.NrSamplesOut = 1764;
6393 break;
6394
6395 case LVM_FS_48000:
6396 ssrcParams.NrSamplesOut = 1920;
6397 break;
6398
6399 default:
6400 ReturnStatus = -1;
6401 break;
6402 }
6403
6404
6405
6406 if( ReturnStatus != SSRC_OK )
6407 {
6408 M4OSA_TRACE1_1(
6409 "M4MCS_intPrepareAudioProcessing:\
6410 Error code %d returned by the SSRC_GetNrSamples function",
6411 ReturnStatus);
6412 return M4MCS_ERR_AUDIO_CONVERSION_FAILED;
6413 }
6414
6415 NrSamplesMin =
6416 (LVM_INT16)((ssrcParams.NrSamplesIn > ssrcParams.NrSamplesOut)
6417 ? ssrcParams.NrSamplesOut : ssrcParams.NrSamplesIn);
6418
6419 while( NrSamplesMin < M4MCS_SSRC_MINBLOCKSIZE )
6420 { /* Don't take blocks smaller that the minimal block size */
6421 ssrcParams.NrSamplesIn = (LVM_INT16)(ssrcParams.NrSamplesIn << 1);
6422 ssrcParams.NrSamplesOut = (LVM_INT16)(ssrcParams.NrSamplesOut << 1);
6423 NrSamplesMin = (LVM_INT16)(NrSamplesMin << 1);
6424 }
6425
6426
6427 pC->iSsrcNbSamplIn = (LVM_INT16)(
6428 ssrcParams.
6429 NrSamplesIn); /* multiplication by NrOfChannels is done below */
6430 pC->iSsrcNbSamplOut = (LVM_INT16)(ssrcParams.NrSamplesOut);
6431
6432 /**
6433 * Allocate buffer for the input of the SSRC */
6434 pC->pSsrcBufferIn =
6435 (M4OSA_MemAddr8)M4OSA_32bitAlignedMalloc(pC->iSsrcNbSamplIn * sizeof(short) \
6436 *pC->pReaderAudioStream->m_nbChannels, M4MCS,
6437 (M4OSA_Char *)"pSsrcBufferIn");
6438
6439 if( M4OSA_NULL == pC->pSsrcBufferIn )
6440 {
6441 M4OSA_TRACE1_0(
6442 "M4MCS_intPrepareVideoDecoder():\
6443 unable to allocate pSsrcBufferIn, returning M4ERR_ALLOC");
6444 return M4ERR_ALLOC;
6445 }
6446 pC->pPosInSsrcBufferIn = (M4OSA_MemAddr8)pC->pSsrcBufferIn;
6447
6448 /**
6449 * Allocate buffer for the output of the SSRC */
6450 pC->pSsrcBufferOut =
6451 (M4OSA_MemAddr8)M4OSA_32bitAlignedMalloc(pC->iSsrcNbSamplOut * sizeof(short) \
6452 *pC->pReaderAudioStream->m_nbChannels, M4MCS,
6453 (M4OSA_Char *)"pSsrcBufferOut");
6454
6455 if( M4OSA_NULL == pC->pSsrcBufferOut )
6456 {
6457 M4OSA_TRACE1_0(
6458 "M4MCS_intPrepareVideoDecoder():\
6459 unable to allocate pSsrcBufferOut, returning M4ERR_ALLOC");
6460 return M4ERR_ALLOC;
6461 }
6462
6463
6464 pC->pLVAudioResampler = LVAudioResamplerCreate(
6465 16, /*gInputParams.lvBTChannelCount*/
6466 (M4OSA_Int16)pC->InputFileProperties.uiNbChannels/*ssrcParams.SSRC_NrOfChannels*/,
6467 (M4OSA_Int32)(pC->AudioEncParams.Frequency)/*ssrcParams.SSRC_Fs_Out*/, 1);
6468
6469 if( M4OSA_NULL == pC->pLVAudioResampler)
6470 {
6471 return M4ERR_ALLOC;
6472 }
6473
6474 LVAudiosetSampleRate(pC->pLVAudioResampler,
6475 /*gInputParams.lvInSampleRate*/
6476 /*pC->pAddedClipCtxt->pSettings->ClipProperties.uiSamplingFrequency*/
6477 pC->InputFileProperties.uiSamplingFrequency/*ssrcParams.SSRC_Fs_In*/);
6478
6479 LVAudiosetVolume(pC->pLVAudioResampler, (M4OSA_Int16)(0x1000 /* 0x7fff */),
6480 (M4OSA_Int16)(0x1000/*0x7fff*/));
6481
6482
6483 /* ________________________ */
6484 /*| |*/
6485 /*| Init the audio encoder |*/
6486 /*|________________________|*/
6487
6488 /* Initialise the audio encoder */
6489
6490 err = pC->pAudioEncoderGlobalFcts->pFctInit(&pC->pAudioEncCtxt,
6491 pC->pCurrentAudioEncoderUserData);
6492
6493 if( M4NO_ERROR != err )
6494 {
6495 M4OSA_TRACE1_1(
6496 "M4MCS_intPrepareAudioProcessing: pAudioEncoderGlobalFcts->pFctInit returns 0x%x",
6497 err);
6498 return err;
6499 }
6500
6501 /* Open the audio encoder */
6502 err = pC->pAudioEncoderGlobalFcts->pFctOpen(pC->pAudioEncCtxt,
6503 &pC->AudioEncParams, &pC->pAudioEncDSI,
6504 M4OSA_NULL /* no grabbing */);
6505
6506 if( M4NO_ERROR != err )
6507 {
6508 M4OSA_TRACE1_1(
6509 "M4MCS_intPrepareAudioProcessing: pAudioEncoderGlobalFcts->pFctOpen returns 0x%x",
6510 err);
6511 return err;
6512 }
6513
6514 /* Allocate the input buffer for the audio encoder */
6515 switch( pC->AudioEncParams.Format )
6516 {
6517 case M4ENCODER_kAMRNB:
6518 pC->audioEncoderGranularity = M4MCS_PCM_AMR_GRANULARITY_SAMPLES;
6519 break;
6520
6521 case M4ENCODER_kAAC:
6522 pC->audioEncoderGranularity = M4MCS_PCM_AAC_GRANULARITY_SAMPLES;
6523 break;
6524
6525 /*FlB 26.02.2009: add mp3 as output format*/
6526 case M4ENCODER_kMP3:
6527 pC->audioEncoderGranularity = M4MCS_PCM_MP3_GRANULARITY_SAMPLES;
6528 break;
6529
6530 default:
6531 break;
6532 }
6533
6534 if( M4ENCODER_kMono == pC->AudioEncParams.ChannelNum )
6535 pC->audioEncoderGranularity *= sizeof(short);
6536 else
6537 pC->audioEncoderGranularity *= sizeof(short) * 2;
6538
6539 pC->pPosInAudioEncoderBuffer = M4OSA_NULL;
6540 pC->pAudioEncoderBuffer =
6541 (M4OSA_MemAddr8)M4OSA_32bitAlignedMalloc(pC->audioEncoderGranularity, M4MCS,
6542 (M4OSA_Char *)"pC->pAudioEncoderBuffer");
6543
6544 /**
6545 * Return with no error */
6546 M4OSA_TRACE3_0("M4MCS_intPrepareAudioProcessing(): returning M4NO_ERROR");
6547 return M4NO_ERROR;
6548 }
6549
6550 /**
6551 ******************************************************************************
6552 * M4OSA_ERR M4MCS_intPrepareWriter(M4MCS_InternalContext* pC);
6553 * @brief Prepare the writer.
6554 * @param pC (IN) MCS private context
6555 * @return M4NO_ERROR No error
6556 * @return Any error returned by an underlaying module
6557 ******************************************************************************
6558 */
M4MCS_intPrepareWriter(M4MCS_InternalContext * pC)6559 static M4OSA_ERR M4MCS_intPrepareWriter( M4MCS_InternalContext *pC )
6560 {
6561 M4OSA_ERR err;
6562 M4OSA_UInt32 uiVersion; /**< To write component version in 3gp writer */
6563 M4OSA_MemAddr8 pDSI = M4OSA_NULL; /**< To create the Decoder Specific Info */
6564 M4SYS_StreamIDValue optionValue; /**< For the setoption calls */
6565 M4OSA_UInt32 TargetedFileSize;
6566 M4OSA_Bool bMULPPSSPS = M4OSA_FALSE;
6567
6568 /**
6569 * Init the writer */
6570 err = pC->pWriterGlobalFcts->pFctOpen(&pC->pWriterContext, pC->pOutputFile,
6571 pC->pOsaFileWritPtr, pC->pTemporaryFile, pC->pOsaFileReadPtr);
6572
6573 if( M4NO_ERROR != err )
6574 {
6575 M4OSA_TRACE1_1(
6576 "M4MCS_intPrepareWriter: pWriterGlobalFcts->pFctOpen returns 0x%x",
6577 err);
6578 return err;
6579 }
6580
6581 /**
6582 * Link to the writer context in the writer interface */
6583 pC->pWriterDataFcts->pWriterContext = pC->pWriterContext;
6584
6585 /**
6586 * Set the product description string in the written file */
6587 err = pC->pWriterGlobalFcts->pFctSetOption(pC->pWriterContext,
6588 M4WRITER_kEmbeddedString, (M4OSA_DataOption)"NXP-SW : MCS ");
6589
6590 if( ( M4NO_ERROR != err) && (( (M4OSA_UInt32)M4ERR_BAD_OPTION_ID)
6591 != err) ) /* this option may not be implemented by some writers */
6592 {
6593 M4OSA_TRACE1_1(
6594 "M4MCS_intPrepareWriter:\
6595 pWriterGlobalFcts->pFctSetOption(M4WRITER_kEmbeddedString) returns 0x%x",
6596 err);
6597 return err;
6598 }
6599
6600 /**
6601 * Set the product version in the written file */
6602 uiVersion =
6603 M4VIDEOEDITING_VERSION_MAJOR * 100 + M4VIDEOEDITING_VERSION_MINOR * 10
6604 + M4VIDEOEDITING_VERSION_REVISION;
6605 err = pC->pWriterGlobalFcts->pFctSetOption(pC->pWriterContext,
6606 M4WRITER_kEmbeddedVersion, (M4OSA_DataOption) &uiVersion);
6607
6608 if( ( M4NO_ERROR != err) && (( (M4OSA_UInt32)M4ERR_BAD_OPTION_ID)
6609 != err) ) /* this option may not be implemented by some writers */
6610 {
6611 M4OSA_TRACE1_1(
6612 "M4MCS_intPrepareWriter: \
6613 pWriterGlobalFcts->pFctSetOption(M4WRITER_kEmbeddedVersion) returns 0x%x",
6614 err);
6615 return err;
6616 }
6617
6618 /**
6619 * If there is a video input, allocate and fill the video stream structures for the writer */
6620 if( pC->novideo == M4OSA_FALSE )
6621 {
6622 /**
6623 * Fill Video properties structure for the AddStream method */
6624 pC->WriterVideoStreamInfo.height = pC->EncodingHeight;
6625 pC->WriterVideoStreamInfo.width = pC->EncodingWidth;
6626 pC->WriterVideoStreamInfo.fps =
6627 0; /**< Not used by the shell/core writer */
6628 pC->WriterVideoStreamInfo.Header.pBuf =
6629 M4OSA_NULL; /**< Will be updated later */
6630 pC->WriterVideoStreamInfo.Header.Size = 0; /**< Will be updated later */
6631
6632 /**
6633 * Fill Video stream description structure for the AddStream method */
6634 switch( pC->EncodingVideoFormat )
6635 {
6636 case M4ENCODER_kMPEG4:
6637 pC->WriterVideoStream.streamType = M4SYS_kMPEG_4;
6638 break;
6639
6640 case M4ENCODER_kH263:
6641 pC->WriterVideoStream.streamType = M4SYS_kH263;
6642 break;
6643
6644 case M4ENCODER_kH264:
6645 pC->WriterVideoStream.streamType = M4SYS_kH264;
6646 break;
6647
6648 case M4ENCODER_kNULL:
6649 switch( pC->InputFileProperties.VideoStreamType )
6650 {
6651 case M4VIDEOEDITING_kMPEG4:
6652 pC->WriterVideoStream.streamType = M4SYS_kMPEG_4;
6653 break;
6654
6655 case M4VIDEOEDITING_kH263:
6656 pC->WriterVideoStream.streamType = M4SYS_kH263;
6657 break;
6658
6659 case M4VIDEOEDITING_kH264:
6660 pC->WriterVideoStream.streamType = M4SYS_kH264;
6661 break;
6662
6663 default:
6664 M4OSA_TRACE1_1(
6665 "M4MCS_intPrepareWriter: case input=M4ENCODER_kNULL, \
6666 unknown format (0x%x),\
6667 returning M4MCS_ERR_UNDEFINED_OUTPUT_VIDEO_FORMAT",
6668 pC->EncodingVideoFormat);
6669 return M4MCS_ERR_UNDEFINED_OUTPUT_VIDEO_FORMAT;
6670 }
6671 break;
6672
6673 default: /**< It should never happen, already tested */
6674 M4OSA_TRACE1_1(
6675 "M4MCS_intPrepareWriter: unknown format (0x%x),\
6676 returning M4MCS_ERR_UNDEFINED_OUTPUT_VIDEO_FORMAT",
6677 pC->EncodingVideoFormat);
6678 return M4MCS_ERR_UNDEFINED_OUTPUT_VIDEO_FORMAT;
6679 }
6680
6681 /**
6682 * Video bitrate value will be the real value */
6683 pC->WriterVideoStream.averageBitrate =
6684 (M4OSA_Int32)pC->uiEncVideoBitrate;
6685 pC->WriterVideoStream.maxBitrate = (M4OSA_Int32)pC->uiEncVideoBitrate;
6686
6687 /**
6688 * most other parameters are "dummy" */
6689 pC->WriterVideoStream.streamID = M4MCS_WRITER_VIDEO_STREAM_ID;
6690 pC->WriterVideoStream.timeScale =
6691 0; /**< Not used by the shell/core writer */
6692 pC->WriterVideoStream.profileLevel =
6693 0; /**< Not used by the shell/core writer */
6694 pC->WriterVideoStream.duration =
6695 0; /**< Not used by the shell/core writer */
6696 pC->WriterVideoStream.decoderSpecificInfoSize =
6697 sizeof(M4WRITER_StreamVideoInfos);
6698 pC->WriterVideoStream.decoderSpecificInfo =
6699 (M4OSA_MemAddr32) &(pC->WriterVideoStreamInfo);
6700
6701 /**
6702 * Update Encoder Header properties for Video stream if needed */
6703 if( M4ENCODER_kH263 == pC->EncodingVideoFormat )
6704 {
6705 /**
6706 * Creates the H263 DSI */
6707 pC->WriterVideoStreamInfo.Header.Size =
6708 7; /**< H263 output DSI is always 7 bytes */
6709 pDSI = (M4OSA_MemAddr8)M4OSA_32bitAlignedMalloc(7, M4MCS, (M4OSA_Char
6710 *)"pC->WriterVideoStreamInfo.Header.pBuf (DSI H263)");
6711
6712 if( M4OSA_NULL == pDSI )
6713 {
6714 M4OSA_TRACE1_0("M4MCS_intPrepareWriter(): unable to allocate pDSI (H263),\
6715 returning M4ERR_ALLOC");
6716 return M4ERR_ALLOC;
6717 }
6718
6719 /**
6720 * Vendor is NXP Software: N, X, P, S. */
6721 pDSI[0] = 'N';
6722 pDSI[1] = 'X';
6723 pDSI[2] = 'P';
6724 pDSI[3] = 'S';
6725
6726 /**
6727 * Decoder version is 0 */
6728 pDSI[4] = 0;
6729
6730 /**
6731 * Level is the sixth byte of the DSI. */
6732 switch( pC->EncodingWidth )
6733 {
6734 case M4ENCODER_SQCIF_Width:
6735 case M4ENCODER_QCIF_Width:
6736 if( ( pC->uiEncVideoBitrate <= M4ENCODER_k64_KBPS)
6737 && (pC->EncodingVideoFramerate <= M4ENCODER_k15_FPS) )
6738 {
6739 pDSI[5] = 10;
6740 }
6741 else if( ( pC->uiEncVideoBitrate <= M4ENCODER_k128_KBPS)
6742 && (pC->EncodingVideoFramerate <= M4ENCODER_k15_FPS) )
6743 {
6744 pDSI[5] = 45;
6745 }
6746 else if( ( pC->uiEncVideoBitrate <= M4ENCODER_k128_KBPS)
6747 && (pC->EncodingVideoFramerate <= M4ENCODER_k30_FPS) )
6748 {
6749 pDSI[5] = 20;
6750 }
6751 else if( ( pC->uiEncVideoBitrate <= M4ENCODER_k384_KBPS)
6752 && (pC->EncodingVideoFramerate <= M4ENCODER_k30_FPS) )
6753 {
6754 pDSI[5] = 30;
6755 }
6756 else if( ( pC->uiEncVideoBitrate
6757 <= M4ENCODER_k800_KBPS/*2048*/)
6758 && (pC->EncodingVideoFramerate <= M4ENCODER_k30_FPS) )
6759 {
6760 pDSI[5] = 40;
6761 }
6762 break;
6763
6764 case M4ENCODER_CIF_Width:
6765 if( ( pC->uiEncVideoBitrate <= M4ENCODER_k128_KBPS)
6766 && (pC->EncodingVideoFramerate <= M4ENCODER_k15_FPS) )
6767 {
6768 pDSI[5] = 20;
6769 }
6770 else if( ( pC->uiEncVideoBitrate <= M4ENCODER_k384_KBPS)
6771 && (pC->EncodingVideoFramerate <= M4ENCODER_k30_FPS) )
6772 {
6773 pDSI[5] = 30;
6774 }
6775 else if( ( pC->uiEncVideoBitrate
6776 <= M4ENCODER_k800_KBPS/*2048*/)
6777 && (pC->EncodingVideoFramerate <= M4ENCODER_k30_FPS) )
6778 {
6779 pDSI[5] = 40;
6780 }
6781 break;
6782
6783 default:
6784 break;
6785 }
6786
6787 /**
6788 * Profile is the seventh byte of the DSI. */
6789 pDSI[6] = 0;
6790
6791 pC->WriterVideoStreamInfo.Header.pBuf = pDSI;
6792 }
6793 else if( M4ENCODER_kNULL == pC->EncodingVideoFormat )
6794 {
6795 /* If we copy the stream from the input, we copy its DSI */
6796
6797 pC->WriterVideoStreamInfo.Header.Size = pC->pReaderVideoStream->
6798 m_basicProperties.m_decoderSpecificInfoSize;
6799 pC->WriterVideoStreamInfo.Header.pBuf =
6800 (M4OSA_MemAddr8)pC->pReaderVideoStream->
6801 m_basicProperties.m_pDecoderSpecificInfo;
6802
6803 }
6804 /* otherwise (MPEG4), the DSI will be recovered from the encoder later on. */
6805
6806 /*+CRLV6775 - H.264 Trimming */
6807 if( pC->bH264Trim == M4OSA_TRUE )
6808 {
6809 bMULPPSSPS = M4OSA_TRUE;
6810 err = pC->pWriterGlobalFcts->pFctSetOption(pC->pWriterContext,
6811 (M4OSA_UInt32)M4WRITER_kMUL_PPS_SPS,
6812 (M4OSA_DataOption) &bMULPPSSPS);
6813
6814 if( ( M4NO_ERROR != err)
6815 && (( (M4OSA_UInt32)M4ERR_BAD_OPTION_ID)
6816 != err) ) /* this option may not be implemented by some writers */
6817 {
6818 M4OSA_TRACE1_1(
6819 "M4MCS_intPrepareWriter:\
6820 pWriterGlobalFcts->pFctSetOption(M4WRITER_kMUL_PPS_SPS) returns 0x%x",
6821 err);
6822 return err;
6823 }
6824 }
6825 /*-CRLV6775 - H.264 Trimming */
6826 /**
6827 * Add the video stream */
6828 err = pC->pWriterGlobalFcts->pFctAddStream(pC->pWriterContext,
6829 &pC->WriterVideoStream);
6830
6831 if( M4NO_ERROR != err )
6832 {
6833 M4OSA_TRACE1_1(
6834 "M4MCS_intPrepareWriter: pWriterGlobalFcts->pFctAddStream(video) returns 0x%x!",
6835 err);
6836 return err;
6837 }
6838
6839 /**
6840 * Update AU properties for video stream */
6841 pC->WriterVideoAU.stream = &(pC->WriterVideoStream);
6842 pC->WriterVideoAU.dataAddress = M4OSA_NULL;
6843 pC->WriterVideoAU.size = 0;
6844 pC->WriterVideoAU.CTS = 0; /** Reset time */
6845 pC->WriterVideoAU.DTS = 0;
6846 pC->WriterVideoAU.attribute = AU_RAP;
6847 pC->WriterVideoAU.nbFrag = 0; /** No fragment */
6848 pC->WriterVideoAU.frag = M4OSA_NULL;
6849
6850 /**
6851 * Set the writer max video AU size */
6852 optionValue.streamID = M4MCS_WRITER_VIDEO_STREAM_ID;
6853 optionValue.value = pC->uiVideoMaxAuSize;
6854 err = pC->pWriterGlobalFcts->pFctSetOption(pC->pWriterContext,
6855 (M4OSA_UInt32)M4WRITER_kMaxAUSize,
6856 (M4OSA_DataOption) &optionValue);
6857
6858 if( M4NO_ERROR != err )
6859 {
6860 M4OSA_TRACE1_1(
6861 "M4MCS_intPrepareWriter: \
6862 pWriterGlobalFcts->pFctSetOption(M4WRITER_kMaxAUSize, video) returns 0x%x!",
6863 err);
6864 return err;
6865 }
6866
6867 /**
6868 * Set the writer max video chunk size */
6869 optionValue.value = pC->uiVideoMaxChunckSize;
6870 err = pC->pWriterGlobalFcts->pFctSetOption(pC->pWriterContext,
6871 (M4OSA_UInt32)M4WRITER_kMaxChunckSize,
6872 (M4OSA_DataOption) &optionValue);
6873
6874 if( ( M4NO_ERROR != err) && (( (M4OSA_UInt32)M4ERR_BAD_OPTION_ID)
6875 != err) ) /* this option may not be implemented by some writers */
6876 {
6877 M4OSA_TRACE1_1(
6878 "M4MCS_intPrepareWriter:\
6879 pWriterGlobalFcts->pFctSetOption(M4WRITER_kMaxAUSize, video) returns 0x%x!",
6880 err);
6881 return err;
6882 }
6883 }
6884
6885 /**
6886 * If there is an audio input, allocate and fill the audio stream structures for the writer */
6887 if( pC->noaudio == M4OSA_FALSE )
6888 {
6889 M4WRITER_StreamAudioInfos streamAudioInfo;
6890
6891 streamAudioInfo.nbSamplesPerSec = 0; /**< unused by our shell writer */
6892 streamAudioInfo.nbBitsPerSample = 0; /**< unused by our shell writer */
6893 streamAudioInfo.nbChannels = 1; /**< unused by our shell writer */
6894
6895 pC->WriterAudioStream.averageBitrate =
6896 0; /**< It is not used by the shell, the DSI is taken into account instead */
6897 pC->WriterAudioStream.maxBitrate =
6898 0; /**< Not used by the shell/core writer */
6899
6900 /**
6901 * Fill Audio stream description structure for the AddStream method */
6902 switch( pC->AudioEncParams.Format )
6903 {
6904 case M4ENCODER_kAMRNB:
6905 pC->WriterAudioStream.streamType = M4SYS_kAMR;
6906 break;
6907
6908 case M4ENCODER_kAAC:
6909 pC->WriterAudioStream.streamType = M4SYS_kAAC;
6910 pC->WriterAudioStream.averageBitrate =
6911 pC->AudioEncParams.Bitrate;
6912 pC->WriterAudioStream.maxBitrate = pC->AudioEncParams.Bitrate;
6913 break;
6914
6915 /*FlB 26.02.2009: add mp3 as output format*/
6916 case M4ENCODER_kMP3:
6917 pC->WriterAudioStream.streamType = M4SYS_kMP3;
6918 break;
6919
6920 case M4ENCODER_kAudioNULL:
6921 switch( pC->InputFileProperties.AudioStreamType )
6922 {
6923 case M4VIDEOEDITING_kAMR_NB:
6924 pC->WriterAudioStream.streamType = M4SYS_kAMR;
6925 break;
6926 /*FlB 26.02.2009: add mp3 as output format*/
6927 case M4VIDEOEDITING_kMP3:
6928 pC->WriterAudioStream.streamType = M4SYS_kMP3;
6929 break;
6930
6931 case M4VIDEOEDITING_kAAC:
6932 case M4VIDEOEDITING_kAACplus:
6933 case M4VIDEOEDITING_keAACplus:
6934 pC->WriterAudioStream.streamType = M4SYS_kAAC;
6935 pC->WriterAudioStream.averageBitrate =
6936 pC->AudioEncParams.Bitrate;
6937 pC->WriterAudioStream.maxBitrate =
6938 pC->AudioEncParams.Bitrate;
6939 break;
6940
6941 case M4VIDEOEDITING_kEVRC:
6942 pC->WriterAudioStream.streamType = M4SYS_kEVRC;
6943 break;
6944
6945 case M4VIDEOEDITING_kNoneAudio:
6946 case M4VIDEOEDITING_kPCM:
6947 case M4VIDEOEDITING_kNullAudio:
6948 case M4VIDEOEDITING_kUnsupportedAudio:
6949 break;
6950 }
6951 break;
6952
6953 default: /**< It should never happen, already tested */
6954 M4OSA_TRACE1_1(
6955 "M4MCS_intPrepareWriter: \
6956 unknown format (0x%x), returning M4MCS_ERR_UNDEFINED_OUTPUT_AUDIO_FORMAT",
6957 pC->AudioEncParams.Format);
6958 return M4MCS_ERR_UNDEFINED_OUTPUT_AUDIO_FORMAT;
6959 }
6960
6961 /**
6962 * MCS produces only AMR-NB output */
6963 pC->WriterAudioStream.streamID = M4MCS_WRITER_AUDIO_STREAM_ID;
6964 pC->WriterAudioStream.duration =
6965 0; /**< Not used by the shell/core writer */
6966 pC->WriterAudioStream.profileLevel =
6967 0; /**< Not used by the shell/core writer */
6968 pC->WriterAudioStream.timeScale = pC->AudioEncParams.Frequency;
6969
6970 if( pC->AudioEncParams.Format == M4ENCODER_kAudioNULL )
6971 {
6972 /* If we copy the stream from the input, we copy its DSI */
6973 streamAudioInfo.Header.Size = pC->pReaderAudioStream->
6974 m_basicProperties.m_decoderSpecificInfoSize;
6975 streamAudioInfo.Header.pBuf =
6976 (M4OSA_MemAddr8)pC->pReaderAudioStream->
6977 m_basicProperties.m_pDecoderSpecificInfo;
6978 }
6979 else
6980 {
6981 if( pC->pAudioEncDSI.pInfo != M4OSA_NULL )
6982 {
6983 /* Use the DSI given by the encoder open() */
6984 streamAudioInfo.Header.Size = pC->pAudioEncDSI.infoSize;
6985 streamAudioInfo.Header.pBuf = pC->pAudioEncDSI.pInfo;
6986 }
6987 else
6988 {
6989 /* Writer will put a default Philips DSI */
6990 streamAudioInfo.Header.Size = 0;
6991 streamAudioInfo.Header.pBuf = M4OSA_NULL;
6992 }
6993 }
6994
6995 /**
6996 * Our writer shell interface is a little tricky: we put M4WRITER_StreamAudioInfos
6997 in the DSI pointer... */
6998 pC->WriterAudioStream.decoderSpecificInfo =
6999 (M4OSA_MemAddr32) &streamAudioInfo;
7000
7001 /**
7002 * Add the audio stream to the writer */
7003 err = pC->pWriterGlobalFcts->pFctAddStream(pC->pWriterContext,
7004 &pC->WriterAudioStream);
7005
7006 if( M4NO_ERROR != err )
7007 {
7008 M4OSA_TRACE1_1(
7009 "M4MCS_intPrepareWriter: pWriterGlobalFcts->pFctAddStream(audio) returns 0x%x",
7010 err);
7011 return err;
7012 }
7013
7014 /**
7015 * Link the AU and the stream */
7016 pC->WriterAudioAU.stream = &(pC->WriterAudioStream);
7017 pC->WriterAudioAU.dataAddress = M4OSA_NULL;
7018 pC->WriterAudioAU.size = 0;
7019 pC->WriterAudioAU.CTS = 0; /** Reset time */
7020 pC->WriterAudioAU.DTS = 0;
7021 pC->WriterAudioAU.attribute = 0;
7022 pC->WriterAudioAU.nbFrag = 0; /** No fragment */
7023 pC->WriterAudioAU.frag = M4OSA_NULL;
7024
7025 /**
7026 * Set the writer audio max AU size */
7027 /* As max bitrate is now 320kbps instead of 128kbps, max AU
7028 * size has to be increased adapt the max AU size according to the stream type and the
7029 * channels numbers*/
7030 /* After tests, a margin of 3 is taken (2 was not enough and raises to memory overwrite)
7031 */
7032 //pC->uiAudioMaxAuSize = M4MCS_AUDIO_MAX_AU_SIZE;
7033 switch( pC->WriterAudioStream.streamType )
7034 {
7035 case M4SYS_kAMR:
7036 pC->uiAudioMaxAuSize = M4MCS_PCM_AMR_GRANULARITY_SAMPLES
7037 * (( pC->InputFileProperties.uiNbChannels
7038 * sizeof(short)) + 3);
7039 break;
7040
7041 case M4SYS_kMP3:
7042 pC->uiAudioMaxAuSize = M4MCS_PCM_MP3_GRANULARITY_SAMPLES
7043 * (( pC->InputFileProperties.uiNbChannels
7044 * sizeof(short)) + 3);
7045 break;
7046
7047 case M4SYS_kAAC:
7048 pC->uiAudioMaxAuSize = M4MCS_PCM_AAC_GRANULARITY_SAMPLES
7049 * (( pC->InputFileProperties.uiNbChannels
7050 * sizeof(short)) + 3);
7051 break;
7052 /*case M4SYS_kEVRC:
7053 pC->uiAudioMaxAuSize = M4MCS_PCM_EVRC_GRANULARITY_SAMPLES*
7054 ((pC->InputFileProperties.uiNbChannels * sizeof(short))+3);
7055 break;*/
7056 default: /**< It should never happen, already tested */
7057 M4OSA_TRACE1_1(
7058 "M4MCS_intPrepareWriter: unknown format (0x%x),\
7059 returning M4MCS_ERR_UNDEFINED_OUTPUT_AUDIO_FORMAT",
7060 pC->WriterAudioStream.streamType);
7061 return M4MCS_ERR_UNDEFINED_OUTPUT_AUDIO_FORMAT;
7062 }
7063
7064 optionValue.streamID = M4MCS_WRITER_AUDIO_STREAM_ID;
7065 optionValue.value = pC->uiAudioMaxAuSize;
7066 err = pC->pWriterGlobalFcts->pFctSetOption(pC->pWriterContext,
7067 (M4OSA_UInt32)M4WRITER_kMaxAUSize,
7068 (M4OSA_DataOption) &optionValue);
7069
7070 if( M4NO_ERROR != err )
7071 {
7072 M4OSA_TRACE1_1(
7073 "M4MCS_intPrepareWriter: pWriterGlobalFcts->pFctSetOption(audio,\
7074 M4WRITER_kMaxAUSize) returns 0x%x",
7075 err);
7076 return err;
7077 }
7078
7079 optionValue.value = M4MCS_AUDIO_MAX_CHUNK_SIZE;
7080 err = pC->pWriterGlobalFcts->pFctSetOption(pC->pWriterContext,
7081 (M4OSA_UInt32)M4WRITER_kMaxChunckSize,
7082 (M4OSA_DataOption) &optionValue);
7083
7084 if( ( M4NO_ERROR != err) && (( (M4OSA_UInt32)M4ERR_BAD_OPTION_ID)
7085 != err) ) /* this option may not be implemented by some writers */
7086 {
7087 M4OSA_TRACE1_1(
7088 "M4MCS_intPrepareWriter: pWriterGlobalFcts->pFctSetOption(audio,\
7089 M4WRITER_kMaxChunckSize) returns 0x%x",
7090 err);
7091 return err;
7092 }
7093 }
7094
7095 /*
7096 * Set the limitation size of the writer */
7097 TargetedFileSize = pC->uiMaxFileSize;
7098 /* add 1 kB margin */
7099 if( TargetedFileSize > 8192 )
7100 TargetedFileSize -= 1024;
7101
7102 err = pC->pWriterGlobalFcts->pFctSetOption(pC->pWriterContext,
7103 (M4OSA_UInt32)M4WRITER_kMaxFileSize,
7104 (M4OSA_DataOption) &TargetedFileSize);
7105
7106 if( ( M4NO_ERROR != err) && (( (M4OSA_UInt32)M4ERR_BAD_OPTION_ID)
7107 != err) ) /* this option may not be implemented by some writers */
7108 {
7109 M4OSA_TRACE1_1(
7110 "M4MCS_intPrepareWriter: pWriterGlobalFcts->pFctSetOption\
7111 (M4WRITER_kMaxFileSize) returns 0x%x!",
7112 err);
7113 return err;
7114 }
7115
7116 /**
7117 * Close the stream registering in order to be ready to write data */
7118 err = pC->pWriterGlobalFcts->pFctStartWriting(pC->pWriterContext);
7119
7120 if( M4NO_ERROR != err )
7121 {
7122 M4OSA_TRACE1_1(
7123 "M4MCS_intPrepareWriter: pWriterGlobalFcts->pFctStartWriting returns 0x%x",
7124 err);
7125 return err;
7126 }
7127
7128 /**
7129 * Return with no error */
7130 M4OSA_TRACE3_0("M4MCS_intPrepareWriter(): returning M4NO_ERROR");
7131 return M4NO_ERROR;
7132 }
7133
7134 /**
7135 ******************************************************************************
7136 * M4OSA_ERR M4MCS_intPrepareAudioBeginCut(M4MCS_InternalContext* pC);
7137 * @brief DO the audio begin cut.
7138 * @param pC (IN) MCS private context
7139 * @return M4NO_ERROR No error
7140 * @return Any error returned by an underlaying module
7141 ******************************************************************************
7142 */
M4MCS_intPrepareAudioBeginCut(M4MCS_InternalContext * pC)7143 static M4OSA_ERR M4MCS_intPrepareAudioBeginCut( M4MCS_InternalContext *pC )
7144 {
7145 M4OSA_ERR err;
7146 M4OSA_Int32 iCts;
7147 M4OSA_UInt32 uiFrameSize;
7148
7149 if( pC->noaudio )
7150 return M4NO_ERROR;
7151
7152 /**
7153 * Check if an audio begin cut is needed */
7154 if( ( M4OSA_NULL == pC->pReaderAudioStream) || (0 == pC->uiBeginCutTime) )
7155 {
7156 /**
7157 * Return with no error */
7158 M4OSA_TRACE3_0(
7159 "M4MCS_intPrepareAudioBeginCut(): returning M4NO_ERROR (a)");
7160 return M4NO_ERROR;
7161 }
7162
7163 /**
7164 * Jump at the begin cut time */
7165 iCts = pC->uiBeginCutTime;
7166 err = pC->m_pReader->m_pFctJump(pC->pReaderContext,
7167 (M4_StreamHandler *)pC->pReaderAudioStream, &iCts);
7168
7169 if( M4NO_ERROR != err )
7170 {
7171 M4OSA_TRACE1_1(
7172 "M4MCS_intPrepareAudioBeginCut: m_pFctJump(Audio) returns 0x%x!",
7173 err);
7174 return err;
7175 }
7176
7177 /**
7178 * Remember audio begin cut offset */
7179 pC->iAudioCtsOffset = iCts;
7180
7181 /**
7182 * AMR-NB & EVRC: there may be many frames per AU.
7183 * In that case we need to slice the first AU to keep the 20 ms cut precision */
7184 if( ( M4DA_StreamTypeAudioAmrNarrowBand
7185 == pC->pReaderAudioStream->m_basicProperties.m_streamType)
7186 || (M4DA_StreamTypeAudioEvrc
7187 == pC->pReaderAudioStream->m_basicProperties.m_streamType) )
7188 {
7189 /**
7190 * If the next frame CTS is lower than the begin cut time,
7191 * we must read the AU and parse its frames to reach the
7192 * nearest to the begin cut */
7193 if( ( iCts + 20) < (M4OSA_Int32)pC->uiBeginCutTime )
7194 {
7195 /**
7196 * Read the first audio AU after the jump */
7197 err = pC->m_pReaderDataIt->m_pFctGetNextAu(pC->pReaderContext,
7198 (M4_StreamHandler *)pC->pReaderAudioStream,
7199 &pC->ReaderAudioAU);
7200
7201 if( M4WAR_NO_MORE_AU == err )
7202 {
7203 M4OSA_TRACE1_0(
7204 "M4MCS_intPrepareAudioBeginCut(): m_pReaderDataIt->m_pFctGetNextAu(audio)\
7205 returns M4WAR_NO_MORE_AU! Returning M4NO_ERROR");
7206 return
7207 M4NO_ERROR; /**< no fatal error here, we should be able to pursue */
7208 }
7209 else if( M4NO_ERROR != err )
7210 {
7211 M4OSA_TRACE1_1(
7212 "M4MCS_intPrepareAudioBeginCut(): m_pReaderDataIt->m_pFctGetNextAu(Audio)\
7213 returns 0x%x",
7214 err);
7215 return err;
7216 }
7217
7218 /**
7219 * While the next AU has a lower CTS than the begin cut time, we advance to
7220 the next frame */
7221 while( ( iCts + 20) <= (M4OSA_Int32)pC->uiBeginCutTime )
7222 {
7223 /**
7224 * Get the size of the frame */
7225 switch( pC->pReaderAudioStream->m_basicProperties.m_streamType )
7226 {
7227 case M4DA_StreamTypeAudioAmrNarrowBand:
7228 uiFrameSize = M4MCS_intGetFrameSize_AMRNB(
7229 pC->ReaderAudioAU.m_dataAddress);
7230 break;
7231
7232 case M4DA_StreamTypeAudioEvrc:
7233 uiFrameSize = M4MCS_intGetFrameSize_EVRC(
7234 pC->ReaderAudioAU.m_dataAddress);
7235 break;
7236
7237 default:
7238 uiFrameSize = 0;
7239 break;
7240 }
7241
7242 if( 0 == uiFrameSize )
7243 {
7244 /**
7245 * Corrupted frame! We get out of this mess!
7246 * We don't want to crash here... */
7247 M4OSA_TRACE1_0(
7248 "M4MCS_intPrepareAudioBeginCut(): \
7249 M4MCS_intGetFrameSize_xxx returns 0! Returning M4NO_ERROR");
7250 return
7251 M4NO_ERROR; /**< no fatal error here, we should be able to pursue */
7252 }
7253
7254 /**
7255 * Go to the next frame */
7256 pC->ReaderAudioAU.m_dataAddress += uiFrameSize;
7257 pC->ReaderAudioAU.m_size -= uiFrameSize;
7258
7259 /**
7260 * Get the CTS of the next frame */
7261 iCts += 20; /**< AMR, EVRC frame duration is always 20 ms */
7262 pC->ReaderAudioAU.m_CTS = iCts;
7263 pC->ReaderAudioAU.m_DTS = iCts;
7264 }
7265
7266 /**
7267 * Update the audio begin cut offset */
7268 pC->iAudioCtsOffset = iCts;
7269 }
7270 }
7271
7272 /**
7273 * Return with no error */
7274 M4OSA_TRACE3_0("M4MCS_intPrepareAudioBeginCut(): returning M4NO_ERROR");
7275 return M4NO_ERROR;
7276 }
7277
7278 /**
7279 ******************************************************************************
7280 * M4OSA_ERR M4MCS_intStepEncoding(M4MCS_InternalContext* pC, M4OSA_UInt8* pProgress)
7281 ******************************************************************************
7282 */
M4MCS_intStepEncoding(M4MCS_InternalContext * pC,M4OSA_UInt8 * pProgress)7283 static M4OSA_ERR M4MCS_intStepEncoding( M4MCS_InternalContext *pC,
7284 M4OSA_UInt8 *pProgress )
7285 {
7286 M4OSA_ERR err;
7287 M4OSA_UInt32 uiAudioStepCount = 0;
7288
7289 /* ---------- VIDEO TRANSCODING ---------- */
7290
7291 if( ( pC->novideo == M4OSA_FALSE) && (M4MCS_kStreamState_STARTED
7292 == pC->VideoState) ) /**< If the video encoding is going on */
7293 {
7294 if( pC->EncodingVideoFormat == M4ENCODER_kNULL )
7295 {
7296 err = M4MCS_intVideoNullEncoding(pC);
7297 }
7298 else
7299 {
7300 err = M4MCS_intVideoTranscoding(pC);
7301 }
7302
7303 /**
7304 * No more space, quit properly */
7305 if( M4WAR_WRITER_STOP_REQ == err )
7306 {
7307 *pProgress = (M4OSA_UInt8)(( ( (M4OSA_UInt32)pC->dViDecCurrentCts
7308 - pC->uiBeginCutTime) * 100)
7309 / (pC->uiEndCutTime - pC->uiBeginCutTime));
7310
7311 pC->State = M4MCS_kState_FINISHED;
7312
7313 /* bad file produced on very short 3gp file */
7314 if( pC->dViDecCurrentCts - pC->uiBeginCutTime == 0 )
7315 {
7316 /* Nothing has been encoded -> bad produced file -> error returned */
7317 M4OSA_TRACE2_0(
7318 "M4MCS_intStepEncoding(): video transcoding returns\
7319 M4MCS_ERR_OUTPUT_FILE_SIZE_TOO_SMALL");
7320 return M4MCS_ERR_OUTPUT_FILE_SIZE_TOO_SMALL;
7321 }
7322 else
7323 {
7324 #ifndef M4MCS_AUDIOONLY
7325 /* clean AIR context needed to keep media aspect ratio*/
7326
7327 if( M4OSA_NULL != pC->m_air_context )
7328 {
7329 err = M4AIR_cleanUp(pC->m_air_context);
7330
7331 if( err != M4NO_ERROR )
7332 {
7333 M4OSA_TRACE1_1(
7334 "M4xVSS_PictureCallbackFct: Error when cleaning AIR: 0x%x",
7335 err);
7336 return err;
7337 }
7338 pC->m_air_context = M4OSA_NULL;
7339 }
7340
7341 #endif /*M4MCS_AUDIOONLY*/
7342
7343 M4OSA_TRACE2_0(
7344 "M4MCS_intStepEncoding(): video transcoding returns M4MCS_ERR_NOMORE_SPACE");
7345 return M4MCS_ERR_NOMORE_SPACE;
7346 }
7347 }
7348
7349 /**< The input plane is null because the input image will be obtained by the
7350 VPP filter from the context */
7351 if( ( M4NO_ERROR != err) && (M4WAR_NO_MORE_AU != err) )
7352 {
7353 M4OSA_TRACE1_1(
7354 "M4MCS_intStepEncoding(): video transcoding returns 0x%x!",
7355 err);
7356 return err;
7357 }
7358 }
7359
7360 /* ---------- AUDIO TRANSCODING ---------- */
7361
7362 if( ( pC->noaudio == M4OSA_FALSE) && (M4MCS_kStreamState_STARTED
7363 == pC->AudioState) ) /**< If there is an audio stream */
7364 {
7365 while(
7366 /**< If the video encoding is running, encode audio until we reach video time */
7367 ( ( pC->novideo == M4OSA_FALSE)
7368 && (M4MCS_kStreamState_STARTED == pC->VideoState)
7369 && (pC->ReaderAudioAU.m_CTS
7370 + pC->m_audioAUDuration < pC->ReaderVideoAU.m_CTS)) ||
7371 /**< If the video encoding is not running, perform 1 step of audio encoding */
7372 (( M4MCS_kStreamState_STARTED == pC->AudioState)
7373 && (uiAudioStepCount < 1)) )
7374 {
7375 uiAudioStepCount++;
7376
7377 /**< check if an adio effect has to be applied*/
7378 err = M4MCS_intCheckAudioEffects(pC);
7379
7380 if( M4NO_ERROR != err )
7381 {
7382 M4OSA_TRACE1_1(
7383 "M4MCS_intStepEncoding(): M4MCS_intCheckAudioEffects returns err: 0x%x",
7384 err);
7385 return err;
7386 }
7387
7388 if( pC->AudioEncParams.Format == M4ENCODER_kAudioNULL )
7389 {
7390 err = M4MCS_intAudioNullEncoding(pC);
7391 }
7392 else /**< Audio transcoding */
7393 {
7394 err = M4MCS_intAudioTranscoding(pC);
7395 }
7396
7397 /**
7398 * No more space, quit properly */
7399 if( M4WAR_WRITER_STOP_REQ == err )
7400 {
7401 *pProgress =
7402 (M4OSA_UInt8)(( ( (M4OSA_UInt32)pC->ReaderAudioAU.m_CTS
7403 - pC->uiBeginCutTime) * 100)
7404 / (pC->uiEndCutTime - pC->uiBeginCutTime));
7405
7406 pC->State = M4MCS_kState_FINISHED;
7407
7408 /* bad file produced on very short 3gp file */
7409 if( pC->ReaderAudioAU.m_CTS - pC->uiBeginCutTime == 0 )
7410 {
7411 /* Nothing has been encoded -> bad produced file -> error returned */
7412 M4OSA_TRACE2_0(
7413 "M4MCS_intStepEncoding():\
7414 audio transcoding returns M4MCS_ERR_OUTPUT_FILE_SIZE_TOO_SMALL");
7415 return M4MCS_ERR_OUTPUT_FILE_SIZE_TOO_SMALL;
7416 }
7417 else
7418 {
7419 #ifndef M4MCS_AUDIOONLY
7420 /* clean AIR context needed to keep media aspect ratio*/
7421
7422 if( M4OSA_NULL != pC->m_air_context )
7423 {
7424 err = M4AIR_cleanUp(pC->m_air_context);
7425
7426 if( err != M4NO_ERROR )
7427 {
7428 M4OSA_TRACE1_1(
7429 "M4xVSS_PictureCallbackFct: Error when cleaning AIR: 0x%x",
7430 err);
7431 return err;
7432 }
7433 pC->m_air_context = M4OSA_NULL;
7434 }
7435
7436 #endif /*M4MCS_AUDIOONLY*/
7437
7438 M4OSA_TRACE2_0(
7439 "M4MCS_intStepEncoding(): \
7440 audio transcoding returns M4MCS_ERR_NOMORE_SPACE");
7441 return M4MCS_ERR_NOMORE_SPACE;
7442 }
7443 }
7444
7445 if( M4WAR_NO_MORE_AU == err )
7446 {
7447 pC->AudioState = M4MCS_kStreamState_FINISHED;
7448 M4OSA_TRACE3_0(
7449 "M4MCS_intStepEncoding(): audio transcoding returns M4WAR_NO_MORE_AU");
7450 break;
7451 }
7452 else if( M4NO_ERROR != err )
7453 {
7454 M4OSA_TRACE1_1(
7455 "M4MCS_intStepEncoding(): audio transcoding returns 0x%x",
7456 err);
7457 return err;
7458 }
7459
7460 /**
7461 * Check for end cut */
7462 /* We absolutely want to have less or same audio duration as video ->
7463 (2*pC->m_audioAUDuration) */
7464 if( (M4OSA_UInt32)pC->ReaderAudioAU.m_CTS
7465 + (2 *pC->m_audioAUDuration) > pC->uiEndCutTime )
7466 {
7467 pC->AudioState = M4MCS_kStreamState_FINISHED;
7468 break;
7469 }
7470 }
7471 }
7472
7473 /* ---------- PROGRESS MANAGEMENT ---------- */
7474
7475 /**
7476 * Compute progress */
7477 if( pC->novideo )
7478 {
7479 if( pC->ReaderAudioAU.m_CTS < pC->uiBeginCutTime )
7480 {
7481 *pProgress = 0;
7482 }
7483 else
7484 {
7485 *pProgress = (M4OSA_UInt8)(( ( (M4OSA_UInt32)pC->ReaderAudioAU.m_CTS
7486 - pC->uiBeginCutTime) * 100)
7487 / (pC->uiEndCutTime - pC->uiBeginCutTime));
7488 }
7489 //printf(": %6.0f\b\b\b\b\b\b\b\b", pC->ReaderAudioAU.m_CTS);
7490
7491 }
7492 else
7493 {
7494 if( pC->dViDecCurrentCts < pC->uiBeginCutTime )
7495 {
7496 *pProgress = 0;
7497 }
7498 else
7499 {
7500 *pProgress = (M4OSA_UInt8)(( ( (M4OSA_UInt32)pC->dViDecCurrentCts
7501 - pC->uiBeginCutTime) * 100)
7502 / (pC->uiEndCutTime - pC->uiBeginCutTime));
7503 }
7504 //printf(": %6.0f\b\b\b\b\b\b\b\b", pC->dViDecCurrentCts);
7505 }
7506
7507 /**
7508 * Sanity check */
7509 if( *pProgress > 99 )
7510 {
7511 *pProgress = 99;
7512 }
7513
7514 /**
7515 * Increment CTS for next step */
7516 if( pC->novideo == M4OSA_FALSE )
7517 {
7518 if( pC->EncodingVideoFormat == M4ENCODER_kNULL )
7519 {
7520 pC->dViDecCurrentCts += 1;
7521 }
7522 else
7523 {
7524 pC->dViDecCurrentCts += pC->dCtsIncrement;
7525 }
7526 }
7527
7528 /**
7529 * The transcoding is finished when no stream is being encoded anymore */
7530 if( ( ( pC->novideo) || (M4MCS_kStreamState_FINISHED == pC->VideoState))
7531 && (( pC->noaudio) || (M4MCS_kStreamState_FINISHED == pC->AudioState)) )
7532 {
7533 /* the AIR part can only be used when video codecs are compiled*/
7534 #ifndef M4MCS_AUDIOONLY
7535 /* clean AIR context needed to keep media aspect ratio*/
7536
7537 if( M4OSA_NULL != pC->m_air_context )
7538 {
7539 err = M4AIR_cleanUp(pC->m_air_context);
7540
7541 if( err != M4NO_ERROR )
7542 {
7543 M4OSA_TRACE1_1(
7544 "M4xVSS_PictureCallbackFct: Error when cleaning AIR: 0x%x",
7545 err);
7546 return err;
7547 }
7548 pC->m_air_context = M4OSA_NULL;
7549 }
7550
7551 #endif /*M4MCS_AUDIOONLY*/
7552 /**/
7553
7554 *pProgress = 100;
7555 pC->State = M4MCS_kState_FINISHED;
7556 M4OSA_TRACE2_0(
7557 "M4MCS_intStepEncoding(): transcoding finished, returning M4MCS_WAR_TRANSCODING_DONE");
7558 return M4MCS_WAR_TRANSCODING_DONE;
7559 }
7560
7561 /**
7562 * Return with no error */
7563 M4OSA_TRACE3_0("M4MCS_intStepEncoding(): returning M4NO_ERROR");
7564 return M4NO_ERROR;
7565 }
7566
7567 /**
7568 ******************************************************************************
7569 * M4OSA_ERR M4MCS_intStepBeginVideoJump(M4MCS_InternalContext* pC)
7570 ******************************************************************************
7571 */
M4MCS_intStepBeginVideoJump(M4MCS_InternalContext * pC)7572 static M4OSA_ERR M4MCS_intStepBeginVideoJump( M4MCS_InternalContext *pC )
7573 {
7574 M4OSA_ERR err;
7575 M4OSA_Int32 iCts;
7576
7577 if( pC->novideo )
7578 {
7579 pC->State = M4MCS_kState_BEGINVIDEODECODE;
7580 return M4NO_ERROR;
7581 }
7582
7583 /**
7584 * Jump to the previous RAP in the clip (first get the time, then jump) */
7585 iCts = (M4OSA_Int32)pC->dViDecStartingCts;
7586 err = pC->m_pReader->m_pFctGetPrevRapTime(pC->pReaderContext,
7587 (M4_StreamHandler *)pC->pReaderVideoStream, &iCts);
7588
7589 if( M4WAR_READER_INFORMATION_NOT_PRESENT == err )
7590 {
7591 /* No RAP table, jump backward and predecode */
7592 iCts = (M4OSA_Int32)pC->dViDecStartingCts - M4MCS_NO_STSS_JUMP_POINT;
7593
7594 if( iCts < 0 )
7595 iCts = 0;
7596 }
7597 else if( M4NO_ERROR != err )
7598 {
7599 M4OSA_TRACE1_1(
7600 "M4MCS_intStepBeginVideoJump: m_pFctGetPrevRapTime returns 0x%x!",
7601 err);
7602 return err;
7603 }
7604
7605 /* + CRLV6775 -H.264 Trimming */
7606
7607 if( M4OSA_TRUE == pC->bH264Trim )
7608 {
7609
7610 // Save jump time for safety, this fix should be generic
7611
7612 M4OSA_Int32 iCtsOri = iCts;
7613
7614
7615 err = pC->m_pReader->m_pFctJump(pC->pReaderContext,
7616 (M4_StreamHandler *)pC->pReaderVideoStream, &iCts);
7617
7618 if( M4NO_ERROR != err )
7619 {
7620 M4OSA_TRACE1_1(
7621 "M4MCS_intStepBeginVideoJump: m_pFctJump(V) returns 0x%x!",
7622 err);
7623 return err;
7624 }
7625
7626 if( pC->ReaderVideoAU1.m_structSize == 0 )
7627 {
7628 /**
7629 * Initializes an access Unit */
7630 err = pC->m_pReader->m_pFctFillAuStruct(pC->pReaderContext,
7631 (M4_StreamHandler *)pC->pReaderVideoStream,
7632 &pC->ReaderVideoAU1);
7633
7634 if( M4NO_ERROR != err )
7635 {
7636 M4OSA_TRACE1_1(
7637 "M4MCS_open(): m_pReader->m_pFctFillAuStruct(video) returns 0x%x",
7638 err);
7639 return err;
7640 }
7641 err = pC->m_pReaderDataIt->m_pFctGetNextAu(pC->pReaderContext,
7642 (M4_StreamHandler *)pC->pReaderVideoStream,
7643 &pC->ReaderVideoAU1);
7644
7645 if( M4WAR_NO_MORE_AU == err )
7646 {
7647 M4OSA_TRACE2_0(
7648 "M4MCS_intVideoNullEncoding(): \
7649 m_pReaderDataIt->m_pFctGetNextAu(video) returns M4WAR_NO_MORE_AU");
7650 /* The audio transcoding is finished */
7651 pC->VideoState = M4MCS_kStreamState_FINISHED;
7652 return err;
7653 }
7654 else if( M4NO_ERROR != err )
7655 {
7656 M4OSA_TRACE1_1(
7657 "M4MCS_intVideoNullEncoding():\
7658 m_pReaderDataIt->m_pFctGetNextAu(video) returns 0x%x",
7659 err);
7660 return err;
7661 }
7662
7663 pC->ReaderVideoAU1.m_structSize = 0;
7664 }
7665
7666 err = H264MCS_ProcessSPS_PPS(pC->m_pInstance,
7667 (M4OSA_UInt8 *)pC->ReaderVideoAU1.m_dataAddress, pC->ReaderVideoAU1.m_size);
7668
7669 if( M4NO_ERROR != err )
7670 {
7671 M4OSA_TRACE1_1(
7672 "M4MCS_intStepBeginVideoJump: H264MCS_ProcessSPS_PPS returns 0x%x!",
7673 err);
7674 return err;
7675 }
7676
7677
7678 // Restore jump time for safety, this fix should be generic
7679
7680 iCts = iCtsOri;
7681
7682
7683 }
7684 /* - CRLV6775 -H.264 Trimming */
7685
7686 /**
7687 * Decode one step */
7688 pC->dViDecCurrentCts = (M4OSA_Double)(iCts + pC->iVideoBeginDecIncr);
7689
7690 /**
7691 * Be sure we don't decode too far */
7692 if( pC->dViDecCurrentCts > pC->dViDecStartingCts )
7693 {
7694 pC->dViDecCurrentCts = pC->dViDecStartingCts;
7695 }
7696
7697 /**
7698 * Decode at least once with the bJump flag to true */
7699 M4OSA_TRACE3_1(
7700 "M4VSS3GPP_intClipDecodeVideoUpToCts: Decoding upTo CTS %.3f",
7701 pC->dViDecCurrentCts);
7702 pC->isRenderDup = M4OSA_FALSE;
7703 err =
7704 pC->m_pVideoDecoder->m_pFctDecode(pC->pViDecCtxt, &pC->dViDecCurrentCts,
7705 M4OSA_TRUE, 0);
7706
7707 if( ( M4NO_ERROR != err) && (M4WAR_NO_MORE_AU != err)
7708 && (err != M4WAR_VIDEORENDERER_NO_NEW_FRAME) )
7709 {
7710 M4OSA_TRACE1_1(
7711 "M4MCS_intStepBeginVideoJump: m_pFctDecode returns 0x%x!", err);
7712 return err;
7713 }
7714
7715 if( err == M4WAR_VIDEORENDERER_NO_NEW_FRAME )
7716 {
7717 M4OSA_TRACE2_0("Decoding output the same frame as before 1");
7718 pC->isRenderDup = M4OSA_TRUE;
7719 }
7720
7721 /**
7722 * Increment decoding cts for the next step */
7723 pC->dViDecCurrentCts += (M4OSA_Double)pC->iVideoBeginDecIncr;
7724
7725 /**
7726 * Update state automaton */
7727 if( pC->dViDecCurrentCts > pC->dViDecStartingCts )
7728 {
7729 /**
7730 * Be sure we don't decode too far */
7731 pC->dViDecCurrentCts = pC->dViDecStartingCts;
7732 pC->State = M4MCS_kState_PROCESSING;
7733 }
7734 else
7735 {
7736 pC->State = M4MCS_kState_BEGINVIDEODECODE;
7737 }
7738
7739 /**
7740 * Return with no error */
7741 M4OSA_TRACE3_0("M4MCS_intStepBeginVideoJump(): returning M4NO_ERROR");
7742 return M4NO_ERROR;
7743 }
7744
7745 /**
7746 ******************************************************************************
7747 * M4OSA_ERR M4MCS_intStepBeginVideoDecode(M4MCS_InternalContext* pC)
7748 ******************************************************************************
7749 */
M4MCS_intStepBeginVideoDecode(M4MCS_InternalContext * pC)7750 static M4OSA_ERR M4MCS_intStepBeginVideoDecode( M4MCS_InternalContext *pC )
7751 {
7752 M4OSA_ERR err;
7753 M4_MediaTime dDecTarget;
7754
7755 if( pC->novideo )
7756 {
7757 pC->State = M4MCS_kState_PROCESSING;
7758 return M4NO_ERROR;
7759 }
7760
7761 /**
7762 * Decode */
7763 dDecTarget = pC->dViDecCurrentCts;
7764 M4OSA_TRACE3_1("M4MCS_intStepBeginDecode: Decoding upTo CTS %.3f",
7765 pC->dViDecCurrentCts);
7766 pC->isRenderDup = M4OSA_FALSE;
7767 err = pC->m_pVideoDecoder->m_pFctDecode(pC->pViDecCtxt, &dDecTarget,
7768 M4OSA_FALSE, 0);
7769
7770 if( ( M4NO_ERROR != err) && (M4WAR_NO_MORE_AU != err)
7771 && (err != M4WAR_VIDEORENDERER_NO_NEW_FRAME) )
7772 {
7773 M4OSA_TRACE1_1(
7774 "M4MCS_intStepBeginVideoDecode: m_pFctDecode returns 0x%x!", err);
7775 return err;
7776 }
7777
7778 if( err == M4WAR_VIDEORENDERER_NO_NEW_FRAME )
7779 {
7780 M4OSA_TRACE2_0("Decoding output the same frame as before 2");
7781 pC->isRenderDup = M4OSA_TRUE;
7782 }
7783
7784 /**
7785 * Increment decoding cts for the next step */
7786 pC->dViDecCurrentCts += (M4OSA_Double)pC->iVideoBeginDecIncr;
7787
7788 /**
7789 * Update state automaton, if needed */
7790 if( ( (M4OSA_UInt32)pC->dViDecCurrentCts > pC->dViDecStartingCts)
7791 || (M4WAR_NO_MORE_AU == err) )
7792 {
7793 /**
7794 * Be sure we don't decode too far */
7795 pC->dViDecCurrentCts = (M4OSA_Double)pC->dViDecStartingCts;
7796 pC->State = M4MCS_kState_PROCESSING;
7797 }
7798
7799 /**
7800 * Return with no error */
7801 M4OSA_TRACE3_0("M4MCS_intStepBeginVideoDecode(): returning M4NO_ERROR");
7802 return M4NO_ERROR;
7803 }
7804
7805 /*****************************/
7806 /* define AMR silence frames */
7807 /*****************************/
7808
7809 #define M4VSS3GPP_AMR_AU_SILENCE_FRAME_048_SIZE 13
7810 #define M4VSS3GPP_AMR_AU_SILENCE_FRAME_048_DURATION 160
7811
7812 #ifdef M4VSS3GPP_SILENCE_FRAMES
7813
7814 const M4OSA_UInt8 M4VSS3GPP_AMR_AU_SILENCE_FRAME_048[
7815 M4VSS3GPP_AMR_AU_SILENCE_FRAME_048_SIZE] =
7816 {
7817 0x04, 0xFF, 0x18, 0xC7, 0xF0, 0x0D, 0x04, 0x33, 0xFF, 0xE0, 0x00, 0x00, 0x00
7818 };
7819 #else
7820
7821 extern
7822 const
7823 M4OSA_UInt8
7824 M4VSS3GPP_AMR_AU_SILENCE_FRAME_048[M4VSS3GPP_AMR_AU_SILENCE_FRAME_048_SIZE];
7825
7826 #endif
7827
7828 /*****************************/
7829 /* define AAC silence frames */
7830 /*****************************/
7831
7832 #define M4VSS3GPP_AAC_AU_SILENCE_MONO_SIZE 4
7833
7834 #ifdef M4VSS3GPP_SILENCE_FRAMES
7835
7836 const M4OSA_UInt8 M4VSS3GPP_AAC_AU_SILENCE_MONO[
7837 M4VSS3GPP_AAC_AU_SILENCE_MONO_SIZE] =
7838 {
7839 0x00, 0xC8, 0x20, 0x07
7840 };
7841 #else
7842
7843 extern const M4OSA_UInt8
7844 M4VSS3GPP_AAC_AU_SILENCE_MONO[M4VSS3GPP_AAC_AU_SILENCE_MONO_SIZE];
7845
7846 #endif
7847
7848 #define M4VSS3GPP_AAC_AU_SILENCE_STEREO_SIZE 6
7849
7850 #ifdef M4VSS3GPP_SILENCE_FRAMES
7851
7852 const M4OSA_UInt8 M4VSS3GPP_AAC_AU_SILENCE_STEREO[
7853 M4VSS3GPP_AAC_AU_SILENCE_STEREO_SIZE] =
7854 {
7855 0x21, 0x10, 0x03, 0x20, 0x54, 0x1C
7856 };
7857 #else
7858
7859 extern const
7860 M4OSA_UInt8
7861 M4VSS3GPP_AAC_AU_SILENCE_STEREO[M4VSS3GPP_AAC_AU_SILENCE_STEREO_SIZE];
7862
7863 #endif
7864
7865 /**
7866 ******************************************************************************
7867 * M4OSA_ERR M4MCS_intAudioNullEncoding(M4MCS_InternalContext* pC)
7868 * @return M4NO_ERROR: No error
7869 ******************************************************************************
7870 */
7871
M4MCS_intAudioNullEncoding(M4MCS_InternalContext * pC)7872 static M4OSA_ERR M4MCS_intAudioNullEncoding( M4MCS_InternalContext *pC )
7873 {
7874 M4OSA_ERR err;
7875
7876 if( pC->noaudio )
7877 return M4NO_ERROR;
7878
7879 /* Check if all audio frame has been written (happens at begin cut) */
7880 if( pC->ReaderAudioAU.m_size == 0 )
7881 {
7882 /**
7883 * Initializes a new AU if needed */
7884 if( pC->ReaderAudioAU1.m_structSize == 0 )
7885 {
7886 /**
7887 * Initializes an access Unit */
7888 err = pC->m_pReader->m_pFctFillAuStruct(pC->pReaderContext,
7889 (M4_StreamHandler *)pC->pReaderAudioStream,
7890 &pC->ReaderAudioAU1);
7891
7892 if( M4NO_ERROR != err )
7893 {
7894 M4OSA_TRACE1_1(
7895 "M4MCS_open(): m_pReader->m_pFctFillAuStruct(audio) returns 0x%x",
7896 err);
7897 return err;
7898 }
7899
7900 pC->m_pDataAddress1 =
7901 (M4OSA_MemAddr8)M4OSA_32bitAlignedMalloc(pC->ReaderAudioAU1.m_maxsize,
7902 M4MCS, (M4OSA_Char *)"Temporary AU1 buffer");
7903
7904 if( pC->m_pDataAddress1 == M4OSA_NULL )
7905 {
7906 M4OSA_TRACE1_0(
7907 "M4MCS_intAudioNullEncoding(): allocation error");
7908 return M4ERR_ALLOC;
7909 }
7910
7911 err = pC->m_pReaderDataIt->m_pFctGetNextAu(pC->pReaderContext,
7912 (M4_StreamHandler *)pC->pReaderAudioStream,
7913 &pC->ReaderAudioAU1);
7914
7915 if( M4WAR_NO_MORE_AU == err )
7916 {
7917 M4OSA_TRACE2_0(
7918 "M4MCS_intAudioNullEncoding():\
7919 m_pReaderDataIt->m_pFctGetNextAu(audio) returns M4WAR_NO_MORE_AU");
7920 /* The audio transcoding is finished */
7921 pC->AudioState = M4MCS_kStreamState_FINISHED;
7922 return err;
7923 }
7924 else if( M4NO_ERROR != err )
7925 {
7926 M4OSA_TRACE1_1(
7927 "M4MCS_intAudioNullEncoding(): \
7928 m_pReaderDataIt->m_pFctGetNextAu(Audio) returns 0x%x",
7929 err);
7930 return err;
7931 }
7932 /*FB 2009.04.02: PR surnxp#616: Crash in MCS while Audio AU copying ,
7933 constant memory reader case*/
7934 if( pC->ReaderAudioAU1.m_maxsize
7935 > pC->pReaderAudioStream->m_basicProperties.m_maxAUSize )
7936 {
7937 /* Constant memory reader case, we need to reallocate the temporary buffers */
7938 M4MCS_intReallocTemporaryAU((M4OSA_MemAddr8
7939 *) &(pC->m_pDataAddress1), pC->ReaderAudioAU1.m_maxsize);
7940 /* pC->m_pDataAddress1 and
7941 pC->m_pDataAddress2 must be reallocated at the same time */
7942 /* because pC->pReaderAudioStream->m_basicProperties.m_maxAUSize take
7943 maximum value. Then the test "if(pC->ReaderAudioAU?.m_maxsize >
7944 pC->pReaderAudioStream->m_basicProperties.m_maxAUSize)" is never true */
7945 /* and the size of the second buffer is never changed. */
7946 M4MCS_intReallocTemporaryAU((M4OSA_MemAddr8
7947 *) &(pC->m_pDataAddress2), pC->ReaderAudioAU1.m_maxsize);
7948 /* pC->m_pDataAddress1 and
7949 pC->m_pDataAddress2 must be reallocated at the same time */
7950 /* Update stream properties */
7951 pC->pReaderAudioStream->m_basicProperties.m_maxAUSize =
7952 pC->ReaderAudioAU1.m_maxsize;
7953 }
7954 /**/
7955 memcpy((void *)pC->m_pDataAddress1,
7956 (void *)pC->ReaderAudioAU1.m_dataAddress,
7957 pC->ReaderAudioAU1.m_size);
7958 }
7959
7960 if( pC->ReaderAudioAU2.m_structSize == 0 )
7961 {
7962 /**
7963 * Initializes an access Unit */
7964 err = pC->m_pReader->m_pFctFillAuStruct(pC->pReaderContext,
7965 (M4_StreamHandler *)pC->pReaderAudioStream,
7966 &pC->ReaderAudioAU2);
7967
7968 if( M4NO_ERROR != err )
7969 {
7970 M4OSA_TRACE1_1(
7971 "M4MCS_open(): m_pReader->m_pFctFillAuStruct(audio) returns 0x%x",
7972 err);
7973 return err;
7974 }
7975 pC->m_pDataAddress2 =
7976 (M4OSA_MemAddr8)M4OSA_32bitAlignedMalloc(pC->ReaderAudioAU2.m_maxsize,
7977 M4MCS, (M4OSA_Char *)"Temporary AU buffer");
7978
7979 if( pC->m_pDataAddress2 == M4OSA_NULL )
7980 {
7981 M4OSA_TRACE1_0(
7982 "M4MCS_intAudioNullEncoding(): allocation error");
7983 return M4ERR_ALLOC;
7984 }
7985 }
7986 /**
7987 * Read the next audio AU in the input file */
7988 if( pC->ReaderAudioAU2.m_CTS > pC->ReaderAudioAU1.m_CTS )
7989 {
7990 memcpy((void *) &pC->ReaderAudioAU,
7991 (void *) &pC->ReaderAudioAU2, sizeof(M4_AccessUnit));
7992 err = pC->m_pReaderDataIt->m_pFctGetNextAu(pC->pReaderContext,
7993 (M4_StreamHandler *)pC->pReaderAudioStream,
7994 &pC->ReaderAudioAU1);
7995
7996 if( pC->ReaderAudioAU1.m_maxsize
7997 > pC->pReaderAudioStream->m_basicProperties.m_maxAUSize )
7998 {
7999 /* Constant memory reader case, we need to reallocate the temporary buffers */
8000 M4MCS_intReallocTemporaryAU((M4OSA_MemAddr8
8001 *) &(pC->m_pDataAddress1), pC->ReaderAudioAU1.m_maxsize);
8002 /* pC->m_pDataAddress1
8003 * and pC->m_pDataAddress2 must be reallocated at the same time *
8004 * because pC->pReaderAudioStream->m_basicProperties.m_maxAUSize take
8005 * maximum value. Then the test "if(pC->ReaderAudioAU?.m_maxsize >
8006 * pC->pReaderAudioStream->m_basicProperties.m_maxAUSize)" is never true *
8007 * and the size of the second buffer is never changed.
8008 */
8009 M4MCS_intReallocTemporaryAU((M4OSA_MemAddr8
8010 *) &(pC->m_pDataAddress2), pC->ReaderAudioAU1.m_maxsize);
8011 /* pC->m_pDataAddress1 and
8012 * pC->m_pDataAddress2 must be reallocated at the same time
8013 * Update stream properties
8014 */
8015 pC->pReaderAudioStream->m_basicProperties.m_maxAUSize =
8016 pC->ReaderAudioAU1.m_maxsize;
8017 }
8018 /**/
8019 memcpy((void *)pC->m_pDataAddress1,
8020 (void *)pC->ReaderAudioAU1.m_dataAddress,
8021 pC->ReaderAudioAU1.m_size);
8022 pC->m_audioAUDuration =
8023 pC->ReaderAudioAU1.m_CTS - pC->ReaderAudioAU2.m_CTS;
8024 pC->ReaderAudioAU.m_dataAddress = pC->m_pDataAddress2;
8025 }
8026 else
8027 {
8028 memcpy((void *) &pC->ReaderAudioAU,
8029 (void *) &pC->ReaderAudioAU1, sizeof(M4_AccessUnit));
8030 err = pC->m_pReaderDataIt->m_pFctGetNextAu(pC->pReaderContext,
8031 (M4_StreamHandler *)pC->pReaderAudioStream,
8032 &pC->ReaderAudioAU2);
8033 /* Crash in MCS while Audio AU copying ,
8034 * constant memory reader case
8035 */
8036 if( pC->ReaderAudioAU2.m_maxsize
8037 > pC->pReaderAudioStream->m_basicProperties.m_maxAUSize )
8038 {
8039 /* Constant memory reader case, we need to reallocate the temporary buffers */
8040 M4MCS_intReallocTemporaryAU((M4OSA_MemAddr8
8041 *) &(pC->m_pDataAddress2), pC->ReaderAudioAU2.m_maxsize);
8042 /* pC->m_pDataAddress1 and
8043 * pC->m_pDataAddress2 must be reallocated at the same time
8044 * because pC->pReaderAudioStream->m_basicProperties.m_maxAUSize take maximum
8045 * value. Then the test "if(pC->ReaderAudioAU?.m_maxsize > pC->pReaderAudioStream->
8046 * m_basicProperties.m_maxAUSize)" is never true
8047 * and the size of the second buffer is never changed.
8048 */
8049 M4MCS_intReallocTemporaryAU((M4OSA_MemAddr8
8050 *) &(pC->m_pDataAddress1), pC->ReaderAudioAU2.m_maxsize);
8051 /* [ END ] 20091008 JFV PR fix surnxpsw#1071: pC->m_pDataAddress1 and
8052 pC->m_pDataAddress2 must be reallocated at the same time */
8053 /* Update stream properties */
8054 pC->pReaderAudioStream->m_basicProperties.m_maxAUSize =
8055 pC->ReaderAudioAU2.m_maxsize;
8056 }
8057 /**/
8058 memcpy((void *)pC->m_pDataAddress2,
8059 (void *)pC->ReaderAudioAU2.m_dataAddress,
8060 pC->ReaderAudioAU2.m_size);
8061 pC->m_audioAUDuration =
8062 pC->ReaderAudioAU2.m_CTS - pC->ReaderAudioAU1.m_CTS;
8063 pC->ReaderAudioAU.m_dataAddress = pC->m_pDataAddress1;
8064 }
8065
8066 if( M4WAR_NO_MORE_AU == err )
8067 {
8068 M4OSA_TRACE2_0(
8069 "M4MCS_intAudioNullEncoding(): \
8070 m_pReaderDataIt->m_pFctGetNextAu(audio) returns M4WAR_NO_MORE_AU");
8071 /* The audio transcoding is finished */
8072 pC->AudioState = M4MCS_kStreamState_FINISHED;
8073 return err;
8074 }
8075 else if( M4NO_ERROR != err )
8076 {
8077 M4OSA_TRACE1_1(
8078 "M4MCS_intAudioNullEncoding(): \
8079 m_pReaderDataIt->m_pFctGetNextAu(Audio) returns 0x%x",
8080 err);
8081 return err;
8082 }
8083 }
8084
8085 /**
8086 * Prepare the writer AU */
8087 err = pC->pWriterDataFcts->pStartAU(pC->pWriterContext,
8088 M4MCS_WRITER_AUDIO_STREAM_ID, &pC->WriterAudioAU);
8089
8090 if( M4NO_ERROR != err )
8091 {
8092 M4OSA_TRACE1_1(
8093 "M4MCS_intAudioNullEncoding(): pWriterDataFcts->pStartAU(Audio) returns 0x%x",
8094 err);
8095 return err;
8096 }
8097
8098 if( pC->uiAudioAUCount
8099 == 0 ) /* If it is the first AU, we set it to silence
8100 (else, errors 0x3841, 0x3847 in our AAC decoder) */
8101 {
8102 if( pC->InputFileProperties.AudioStreamType == M4VIDEOEDITING_kAAC
8103 || pC->InputFileProperties.AudioStreamType
8104 == M4VIDEOEDITING_kAACplus
8105 || pC->InputFileProperties.AudioStreamType
8106 == M4VIDEOEDITING_keAACplus )
8107 {
8108 if( pC->InputFileProperties.uiNbChannels == 1 )
8109 {
8110 pC->WriterAudioAU.size = M4VSS3GPP_AAC_AU_SILENCE_MONO_SIZE;
8111 memcpy((void *)pC->WriterAudioAU.dataAddress,
8112 (void *)M4VSS3GPP_AAC_AU_SILENCE_MONO,
8113 pC->WriterAudioAU.size);
8114 }
8115 else if( pC->InputFileProperties.uiNbChannels == 2 )
8116 {
8117 pC->WriterAudioAU.size = M4VSS3GPP_AAC_AU_SILENCE_STEREO_SIZE;
8118 memcpy((void *)pC->WriterAudioAU.dataAddress,
8119 (void *)M4VSS3GPP_AAC_AU_SILENCE_STEREO,
8120 pC->WriterAudioAU.size);
8121 }
8122 else
8123 {
8124 /* Must never happen ...*/
8125 M4OSA_TRACE1_0(
8126 "M4MCS_intAudioNullEncoding: Bad number of channels in audio input");
8127 return M4MCS_ERR_INVALID_INPUT_FILE;
8128 }
8129 }
8130 else if( pC->InputFileProperties.AudioStreamType
8131 == M4VIDEOEDITING_kAMR_NB )
8132 {
8133 pC->WriterAudioAU.size = M4VSS3GPP_AMR_AU_SILENCE_FRAME_048_SIZE;
8134 memcpy((void *)pC->WriterAudioAU.dataAddress,
8135 (void *)M4VSS3GPP_AMR_AU_SILENCE_FRAME_048,
8136 pC->WriterAudioAU.size);
8137 /* Some remaining AMR AU needs to be copied */
8138 if( pC->ReaderAudioAU.m_size != 0 )
8139 {
8140 /* Update Writer AU */
8141 pC->WriterAudioAU.size += pC->ReaderAudioAU.m_size;
8142 memcpy((void *)(pC->WriterAudioAU.dataAddress
8143 + M4VSS3GPP_AMR_AU_SILENCE_FRAME_048_SIZE),
8144 (void *)pC->ReaderAudioAU.m_dataAddress,
8145 pC->ReaderAudioAU.m_size);
8146 }
8147 }
8148 else
8149 {
8150 /*MP3 case: copy the AU*/
8151 M4OSA_TRACE3_1(
8152 "M4MCS_intAudioNullEncoding(): Copying audio AU: size=%d",
8153 pC->ReaderAudioAU.m_size);
8154 memcpy((void *)pC->WriterAudioAU.dataAddress,
8155 (void *)pC->ReaderAudioAU.m_dataAddress,
8156 pC->ReaderAudioAU.m_size);
8157 pC->WriterAudioAU.size = pC->ReaderAudioAU.m_size;
8158 }
8159 }
8160 else
8161 {
8162 /**
8163 * Copy audio data from reader AU to writer AU */
8164 M4OSA_TRACE3_1(
8165 "M4MCS_intAudioNullEncoding(): Copying audio AU: size=%d",
8166 pC->ReaderAudioAU.m_size);
8167 memcpy((void *)pC->WriterAudioAU.dataAddress,
8168 (void *)pC->ReaderAudioAU.m_dataAddress,
8169 pC->ReaderAudioAU.m_size);
8170 pC->WriterAudioAU.size = pC->ReaderAudioAU.m_size;
8171 }
8172
8173 /**
8174 * Convert CTS unit from milliseconds to timescale */
8175 pC->WriterAudioAU.CTS =
8176 (M4OSA_Time)((( pC->ReaderAudioAU.m_CTS - pC->iAudioCtsOffset)
8177 * (pC->WriterAudioStream.timeScale / 1000.0)));
8178
8179 if( pC->InputFileProperties.AudioStreamType == M4VIDEOEDITING_kAMR_NB
8180 && pC->uiAudioAUCount == 0 )
8181 {
8182 pC->iAudioCtsOffset -=
8183 20; /* Duration of a silence AMR AU, to handle the duration of the added
8184 silence frame */
8185 }
8186 pC->WriterAudioAU.nbFrag = 0;
8187 M4OSA_TRACE3_1("M4MCS_intAudioNullEncoding(): audio AU: CTS=%d ms",
8188 pC->WriterAudioAU.CTS);
8189
8190 /**
8191 * Write it to the output file */
8192 pC->uiAudioAUCount++;
8193 err = pC->pWriterDataFcts->pProcessAU(pC->pWriterContext,
8194 M4MCS_WRITER_AUDIO_STREAM_ID, &pC->WriterAudioAU);
8195
8196 if( M4NO_ERROR != err )
8197 {
8198 M4OSA_TRACE1_1(
8199 "M4MCS_intAudioNullEncoding(): pWriterDataFcts->pProcessAU(Audio) returns 0x%x",
8200 err);
8201 return err;
8202 }
8203
8204 /* All the audio has been written */
8205 pC->ReaderAudioAU.m_size = 0;
8206
8207 /**
8208 * Return with no error */
8209 M4OSA_TRACE3_0("M4MCS_intAudioNullEncoding(): returning M4NO_ERROR");
8210 return M4NO_ERROR;
8211 }
8212
8213 /**
8214 ******************************************************************************
8215 * @brief Init Audio Transcoding
8216 * @return M4NO_ERROR: No error
8217 ******************************************************************************
8218 */
M4MCS_intAudioTranscoding(M4MCS_InternalContext * pC)8219 static M4OSA_ERR M4MCS_intAudioTranscoding( M4MCS_InternalContext *pC )
8220 {
8221 M4OSA_ERR err; /**< General error */
8222
8223 M4OSA_UInt32
8224 uiBytesDec; /**< Nb of bytes available in the decoder OUT buffer */
8225 M4OSA_UInt32
8226 uiDecoder2Ssrc_NbBytes; /**< Nb of bytes copied into the ssrc IN buffer */
8227
8228 int ssrcErr; /**< Error while ssrc processing */
8229 M4OSA_UInt32 uiSsrcInSize; /**< Size in bytes of ssrc intput buffer */
8230 M4OSA_UInt32
8231 uiSsrcInRoom; /**< Nb of bytes available in the ssrc IN buffer */
8232 M4OSA_MemAddr8
8233 pSsrcInput; /**< Pointer to the good buffer location for ssrc input */
8234 M4OSA_UInt32 uiSsrcOutSize; /**< Size in bytes of ssrc output buffer */
8235 M4OSA_UInt32
8236 uiBytesSsrc; /**< Nb of bytes available in the ssrc OUT buffer */
8237
8238 M4OSA_UInt8
8239 needChannelConversion; /**< Flag to indicate if a stereo <-> mono conversion is needed */
8240 M4OSA_UInt32
8241 uiChannelConvertorCoeff; /**< Multiplicative coefficient if stereo
8242 <-> mono conversion is applied */
8243 M4OSA_MemAddr8 pChannelConvertorInput =
8244 M4OSA_NULL; /**< Pointer to the good buffer location for channel convertor input */
8245 M4OSA_UInt32 uiChannelConvertorNbSamples =
8246 0; /**< Nb of pcm samples to convert in channel convertor */
8247 M4OSA_MemAddr8 pChannelConvertorOutput =
8248 M4OSA_NULL; /**< Pointer to the good buffer location for channel convertor output */
8249
8250 M4OSA_Time
8251 frameTimeDelta; /**< Duration of the encoded (then written) data */
8252 M4OSA_UInt32
8253 uiEncoderInRoom; /**< Nb of bytes available in the encoder IN buffer */
8254 M4OSA_UInt32
8255 uiSsrc2Encoder_NbBytes; /**< Nb of bytes copied from the ssrc OUT buffer */
8256 M4OSA_MemAddr8
8257 pEncoderInput; /**< Pointer to the good buffer location for encoder input */
8258 M4ENCODER_AudioBuffer pEncInBuffer; /**< Encoder input buffer for api */
8259 M4ENCODER_AudioBuffer pEncOutBuffer; /**< Encoder output buffer for api */
8260
8261 M4OSA_Int16 *tempBuffOut = M4OSA_NULL;
8262 /*FlB 2009.03.04: apply audio effects if an effect is active*/
8263 M4OSA_Int8 *pActiveEffectNumber = &(pC->pActiveEffectNumber);
8264
8265 uint32_t errCode = M4NO_ERROR;
8266
8267 if( pC->noaudio )
8268 return M4NO_ERROR;
8269
8270 /* _________________ */
8271 /*| |*/
8272 /*| READ AND DECODE |*/
8273 /*|_________________|*/
8274
8275 /* Check if we have to empty the decoder out buffer first */
8276 if( M4OSA_NULL != pC->pPosInDecBufferOut )
8277 {
8278 goto m4mcs_intaudiotranscoding_feed_resampler;
8279 }
8280
8281 err = pC->m_pAudioDecoder->m_pFctStepAudioDec(pC->pAudioDecCtxt,
8282 M4OSA_NULL, &pC->AudioDecBufferOut, M4OSA_FALSE);
8283
8284
8285 if( M4NO_ERROR != err )
8286 {
8287 M4OSA_TRACE1_1(
8288 "M4MCS_intAudioTranscoding(): m_pAudioDecoder->m_pFctStepAudio returns 0x%x",
8289 err);
8290 return err;
8291 }
8292
8293 #ifdef MCS_DUMP_PCM_TO_FILE
8294
8295 fwrite(pC->AudioDecBufferOut.m_dataAddress,
8296 pC->AudioDecBufferOut.m_bufferSize, 1, file_pcm_decoder);
8297
8298 #endif
8299
8300 pC->m_pAudioDecoder->m_pFctGetOptionAudioDec(pC->pAudioDecCtxt,
8301 M4AD_kOptionID_GetAudioAUErrCode, (M4OSA_DataOption) &errCode);
8302
8303 if ( M4WAR_NO_MORE_AU == errCode ) {
8304 pC->AudioState = M4MCS_kStreamState_FINISHED;
8305 M4OSA_TRACE2_0(
8306 "M4MCS_intAudioTranscoding():\
8307 m_pReaderDataIt->m_pFctGetNextAu(audio) returns M4WAR_NO_MORE_AU");
8308 return errCode;
8309 }
8310
8311 /* Set the current position in the decoder out buffer */
8312 pC->pPosInDecBufferOut = pC->AudioDecBufferOut.m_dataAddress;
8313
8314 /* ________________ */
8315 /*| |*/
8316 /*| FEED RESAMPLER |*/
8317 /*|________________|*/
8318
8319 m4mcs_intaudiotranscoding_feed_resampler:
8320
8321 /* Check if we have to empty the ssrc out buffer first */
8322 if( M4OSA_NULL != pC->pPosInSsrcBufferOut )
8323 {
8324 goto m4mcs_intaudiotranscoding_prepare_input_buffer;
8325 }
8326
8327 /* Compute number of bytes remaining in the decoder buffer */
8328 uiSsrcInSize = pC->iSsrcNbSamplIn * sizeof(short)
8329 * pC->pReaderAudioStream->m_nbChannels;
8330 uiBytesDec = ( pC->AudioDecBufferOut.m_dataAddress
8331 + pC->AudioDecBufferOut.m_bufferSize) - pC->pPosInDecBufferOut;
8332
8333 /* Check if we can feed directly the Ssrc with the decoder out buffer */
8334 if( ( pC->pPosInSsrcBufferIn == pC->pSsrcBufferIn)
8335 && (uiBytesDec >= uiSsrcInSize) )
8336 {
8337 pSsrcInput = pC->pPosInDecBufferOut;
8338
8339 /* update data consumed into decoder buffer after resampling */
8340 if( uiBytesDec == uiSsrcInSize )
8341 pC->pPosInDecBufferOut = M4OSA_NULL;
8342 else
8343 pC->pPosInDecBufferOut += uiSsrcInSize;
8344
8345 goto m4mcs_intaudiotranscoding_do_resampling;
8346 }
8347
8348 /**
8349 * Compute remaining space in Ssrc buffer in */
8350 uiSsrcInRoom = ( pC->pSsrcBufferIn + uiSsrcInSize) - pC->pPosInSsrcBufferIn;
8351
8352 /**
8353 * Nb of bytes copied is the minimum between nb of bytes remaining in
8354 * decoder out buffer and space remaining in ssrc in buffer */
8355 uiDecoder2Ssrc_NbBytes =
8356 (uiSsrcInRoom < uiBytesDec) ? uiSsrcInRoom : uiBytesDec;
8357
8358 /**
8359 * Copy from the decoder out buffer into the Ssrc in buffer */
8360 memcpy((void *)pC->pPosInSsrcBufferIn, (void *)pC->pPosInDecBufferOut,
8361 uiDecoder2Ssrc_NbBytes);
8362
8363 /**
8364 * Update the position in the decoder out buffer */
8365 pC->pPosInDecBufferOut += uiDecoder2Ssrc_NbBytes;
8366
8367 /**
8368 * Update the position in the Ssrc in buffer */
8369 pC->pPosInSsrcBufferIn += uiDecoder2Ssrc_NbBytes;
8370
8371 /**
8372 * Check if the decoder buffer out is empty */
8373 if( ( pC->pPosInDecBufferOut - pC->AudioDecBufferOut.m_dataAddress)
8374 == (M4OSA_Int32)pC->AudioDecBufferOut.m_bufferSize )
8375 {
8376 pC->pPosInDecBufferOut = M4OSA_NULL;
8377 }
8378
8379 /* Check if the Ssrc in buffer is ready (= full) */
8380 if( ( pC->pPosInSsrcBufferIn - pC->pSsrcBufferIn)
8381 < (M4OSA_Int32)uiSsrcInSize )
8382 {
8383 goto m4mcs_intaudiotranscoding_end;
8384 }
8385
8386 pSsrcInput = pC->pSsrcBufferIn;
8387
8388 /* update data consumed into ssrc buffer in after resampling (empty) */
8389 pC->pPosInSsrcBufferIn = pC->pSsrcBufferIn;
8390
8391 /* ___________________ */
8392 /*| |*/
8393 /*| DO THE RESAMPLING |*/
8394 /*|___________________|*/
8395
8396 m4mcs_intaudiotranscoding_do_resampling:
8397
8398 /**
8399 * No need for memcopy, we can feed Ssrc directly with the data in the audio
8400 decoder out buffer*/
8401
8402 ssrcErr = 0;
8403
8404 if( pC->pReaderAudioStream->m_nbChannels == 1 )
8405 {
8406 tempBuffOut =
8407 (short *)M4OSA_32bitAlignedMalloc((pC->iSsrcNbSamplOut * sizeof(short) * 2
8408 * ((*pC).InputFileProperties).uiNbChannels),
8409 M4VSS3GPP,(M4OSA_Char *) "tempBuffOut");
8410 memset((void *)tempBuffOut, 0,(pC->iSsrcNbSamplOut * sizeof(short) * 2
8411 * ((*pC).InputFileProperties).uiNbChannels));
8412
8413 LVAudioresample_LowQuality((short *)tempBuffOut, (short *)pSsrcInput,
8414 pC->iSsrcNbSamplOut, pC->pLVAudioResampler);
8415 }
8416 else
8417 {
8418 memset((void *)pC->pSsrcBufferOut, 0, (pC->iSsrcNbSamplOut * sizeof(short)
8419 * ((*pC).InputFileProperties).uiNbChannels));
8420
8421 LVAudioresample_LowQuality((short *)pC->pSsrcBufferOut,
8422 (short *)pSsrcInput, pC->iSsrcNbSamplOut, pC->pLVAudioResampler);
8423 }
8424
8425 if( pC->pReaderAudioStream->m_nbChannels == 1 )
8426 {
8427 From2iToMono_16((short *)tempBuffOut, (short *)pC->pSsrcBufferOut,
8428 (short)pC->iSsrcNbSamplOut);
8429 free(tempBuffOut);
8430 }
8431
8432
8433 if( 0 != ssrcErr )
8434 {
8435 M4OSA_TRACE1_1(
8436 "M4MCS_intAudioTranscoding: SSRC_Process returns 0x%x, \
8437 returning M4MCS_ERR_AUDIO_CONVERSION_FAILED",
8438 ssrcErr);
8439 return M4MCS_ERR_AUDIO_CONVERSION_FAILED;
8440 }
8441
8442 pC->pPosInSsrcBufferOut = pC->pSsrcBufferOut;
8443
8444 /* ______________________ */
8445 /*| |*/
8446 /*| PREPARE INPUT BUFFER |*/
8447 /*|______________________|*/
8448
8449 m4mcs_intaudiotranscoding_prepare_input_buffer:
8450
8451 /* Set the flag for channel conversion requirement */
8452 if( ( pC->AudioEncParams.ChannelNum == M4ENCODER_kMono)
8453 && (pC->pReaderAudioStream->m_nbChannels == 2) )
8454 {
8455 needChannelConversion = 1;
8456 uiChannelConvertorCoeff = 4;
8457 }
8458 else if( ( pC->AudioEncParams.ChannelNum == M4ENCODER_kStereo)
8459 && (pC->pReaderAudioStream->m_nbChannels == 1) )
8460 {
8461 needChannelConversion = 2;
8462 uiChannelConvertorCoeff = 1;
8463 }
8464 else
8465 {
8466 needChannelConversion = 0;
8467 uiChannelConvertorCoeff = 2;
8468 }
8469
8470 /* Compute number of bytes remaining in the Ssrc buffer */
8471 uiSsrcOutSize = pC->iSsrcNbSamplOut * sizeof(short)
8472 * pC->pReaderAudioStream->m_nbChannels;
8473 uiBytesSsrc =
8474 ( pC->pSsrcBufferOut + uiSsrcOutSize) - pC->pPosInSsrcBufferOut;
8475
8476 /* Check if the ssrc buffer is full */
8477 if( pC->pPosInSsrcBufferOut == pC->pSsrcBufferOut )
8478 {
8479 uiSsrc2Encoder_NbBytes =
8480 pC->audioEncoderGranularity * uiChannelConvertorCoeff / 2;
8481
8482 /* Check if we can feed directly the encoder with the ssrc out buffer */
8483 if( ( pC->pPosInAudioEncoderBuffer == M4OSA_NULL)
8484 && (uiBytesSsrc >= uiSsrc2Encoder_NbBytes) )
8485 {
8486 /* update position in ssrc out buffer after encoding */
8487 if( uiBytesSsrc == uiSsrc2Encoder_NbBytes )
8488 pC->pPosInSsrcBufferOut = M4OSA_NULL;
8489 else
8490 pC->pPosInSsrcBufferOut += uiSsrc2Encoder_NbBytes;
8491
8492 /* mark the encoder buffer ready (= full) */
8493 pC->pPosInAudioEncoderBuffer =
8494 pC->pAudioEncoderBuffer + pC->audioEncoderGranularity;
8495
8496 if( needChannelConversion > 0 )
8497 {
8498 /* channel convertor writes directly into encoder buffer */
8499 pEncoderInput = pC->pAudioEncoderBuffer;
8500
8501 pChannelConvertorInput = pC->pSsrcBufferOut;
8502 pChannelConvertorOutput = pC->pAudioEncoderBuffer;
8503 uiChannelConvertorNbSamples =
8504 uiSsrc2Encoder_NbBytes / sizeof(short);
8505
8506 goto m4mcs_intaudiotranscoding_channel_convertor;
8507 }
8508 else
8509 {
8510 /* encode directly from ssrc out buffer */
8511 pEncoderInput = pC->pSsrcBufferOut;
8512
8513 goto m4mcs_intaudiotranscoding_encode_and_write;
8514 }
8515 }
8516 }
8517
8518 /**
8519 * Compute remaining space in encoder buffer in */
8520 if( pC->pPosInAudioEncoderBuffer == M4OSA_NULL )
8521 {
8522 pC->pPosInAudioEncoderBuffer = pC->pAudioEncoderBuffer;
8523 }
8524
8525 uiEncoderInRoom = ( pC->pAudioEncoderBuffer + pC->audioEncoderGranularity)
8526 - pC->pPosInAudioEncoderBuffer;
8527 pEncoderInput = pC->pAudioEncoderBuffer;
8528
8529 /**
8530 * Nb of bytes copied is the minimum between nb of bytes remaining in
8531 * decoder out buffer and space remaining in ssrc in buffer */
8532 uiSsrc2Encoder_NbBytes =
8533 (( uiEncoderInRoom * uiChannelConvertorCoeff / 2) < uiBytesSsrc)
8534 ? (uiEncoderInRoom * uiChannelConvertorCoeff / 2) : uiBytesSsrc;
8535
8536 if( needChannelConversion > 0 )
8537 {
8538 /* channel convertor writes directly into encoder buffer */
8539 pChannelConvertorInput = pC->pPosInSsrcBufferOut;
8540 pChannelConvertorOutput = pC->pPosInAudioEncoderBuffer;
8541 uiChannelConvertorNbSamples = uiSsrc2Encoder_NbBytes / sizeof(short);
8542 }
8543 else
8544 {
8545 /* copy from the ssrc out buffer into the encoder in buffer */
8546 memcpy((void *)pC->pPosInAudioEncoderBuffer, (void *)pC->pPosInSsrcBufferOut,
8547 uiSsrc2Encoder_NbBytes);
8548 }
8549
8550 /* Update position in ssrc out buffer after encoding */
8551 pC->pPosInSsrcBufferOut += uiSsrc2Encoder_NbBytes;
8552
8553 /* Update the position in the encoder in buffer */
8554 pC->pPosInAudioEncoderBuffer +=
8555 uiSsrc2Encoder_NbBytes * 2 / uiChannelConvertorCoeff;
8556
8557 /* Check if the ssrc buffer out is empty */
8558 if( ( pC->pPosInSsrcBufferOut - pC->pSsrcBufferOut)
8559 == (M4OSA_Int32)uiSsrcOutSize )
8560 {
8561 pC->pPosInSsrcBufferOut = M4OSA_NULL;
8562 }
8563
8564 /* go to next statement */
8565 if( needChannelConversion > 0 )
8566 goto m4mcs_intaudiotranscoding_channel_convertor;
8567 else
8568 goto m4mcs_intaudiotranscoding_encode_and_write;
8569
8570 /* _________________ */
8571 /*| |*/
8572 /*| STEREO <-> MONO |*/
8573 /*|_________________|*/
8574
8575 m4mcs_intaudiotranscoding_channel_convertor:
8576
8577 /* convert the input pcm stream to mono or to stereo */
8578 switch( needChannelConversion )
8579 {
8580 case 1: /* stereo to mono */
8581 From2iToMono_16((short *)pChannelConvertorInput,
8582 (short *)pChannelConvertorOutput,
8583 (short)(uiChannelConvertorNbSamples / 2));
8584 break;
8585
8586 case 2: /* mono to stereo */
8587 MonoTo2I_16((short *)pChannelConvertorInput,
8588 (short *)pChannelConvertorOutput,
8589 (short)uiChannelConvertorNbSamples);
8590 break;
8591 }
8592
8593 /* __________________ */
8594 /*| |*/
8595 /*| ENCODE AND WRITE |*/
8596 /*|__________________|*/
8597
8598 m4mcs_intaudiotranscoding_encode_and_write:
8599
8600 /* Check if the encoder in buffer is ready (= full) */
8601 if( ( pC->pPosInAudioEncoderBuffer - pC->pAudioEncoderBuffer)
8602 < (M4OSA_Int32)pC->audioEncoderGranularity )
8603 {
8604 goto m4mcs_intaudiotranscoding_end;
8605 }
8606
8607 /* [Mono] or [Stereo interleaved] : all is in one buffer */
8608 pEncInBuffer.pTableBuffer[0] = pEncoderInput;
8609 pEncInBuffer.pTableBufferSize[0] = pC->audioEncoderGranularity;
8610 pEncInBuffer.pTableBuffer[1] = M4OSA_NULL;
8611 pEncInBuffer.pTableBufferSize[1] = 0;
8612
8613 /* Time in ms from data size, because it is PCM16 samples */
8614 frameTimeDelta =
8615 ( pEncInBuffer.pTableBufferSize[0] * uiChannelConvertorCoeff / 2)
8616 / sizeof(short) / pC->pReaderAudioStream->m_nbChannels;
8617
8618 /**
8619 * Prepare the writer AU */
8620 err = pC->pWriterDataFcts->pStartAU(pC->pWriterContext,
8621 M4MCS_WRITER_AUDIO_STREAM_ID, &pC->WriterAudioAU);
8622
8623 if( M4NO_ERROR != err )
8624 {
8625 M4OSA_TRACE1_1(
8626 "M4MCS_intAudioTranscoding(): pWriterDataFcts->pStartAU(Audio) returns 0x%x",
8627 err);
8628 return err;
8629 }
8630
8631 /*FlB 2009.03.04: apply audio effects if an effect is active*/
8632 if( *pActiveEffectNumber >= 0 && *pActiveEffectNumber < pC->nbEffects )
8633 {
8634 if( pC->pEffects[*pActiveEffectNumber].ExtAudioEffectFct != M4OSA_NULL )
8635 {
8636 M4MCS_ExternalProgress pProgress;
8637 M4OSA_UInt32 tempProgress = 0;
8638 pProgress.uiClipTime = (M4OSA_UInt32)pC->ReaderAudioAU.m_CTS;
8639
8640 pProgress.uiOutputTime = ( pC->WriterAudioAU.CTS * 1000)
8641 / pC->WriterAudioStream.timeScale;
8642 tempProgress = ( (M4OSA_UInt32)pC->ReaderAudioAU.m_CTS
8643 - pC->pEffects[*pActiveEffectNumber].uiStartTime
8644 - pC->uiBeginCutTime) * 1000;
8645 pProgress.uiProgress =
8646 (M4OSA_UInt32)(tempProgress / (M4OSA_UInt32)pC->pEffects[
8647 *pActiveEffectNumber].uiDuration);
8648
8649 err = pC->pEffects[*pActiveEffectNumber].ExtAudioEffectFct(
8650 pC->pEffects[*pActiveEffectNumber].pExtAudioEffectFctCtxt,
8651 (M4OSA_Int16 *)pEncInBuffer.pTableBuffer[0],
8652 pEncInBuffer.pTableBufferSize[0], &pProgress);
8653
8654 if( err != M4NO_ERROR )
8655 {
8656 M4OSA_TRACE1_1(
8657 "M4MCS_intAudioTranscoding(): ExtAudioEffectFct() returns 0x%x",
8658 err);
8659 return err;
8660 }
8661 }
8662 }
8663
8664 /**
8665 * Prepare output buffer */
8666 pEncOutBuffer.pTableBuffer[0] =
8667 (M4OSA_MemAddr8)pC->WriterAudioAU.dataAddress;
8668 pEncOutBuffer.pTableBufferSize[0] = 0;
8669
8670 #ifdef MCS_DUMP_PCM_TO_FILE
8671
8672 fwrite(pEncInBuffer.pTableBuffer[0], pEncInBuffer.pTableBufferSize[0], 1,
8673 file_pcm_encoder);
8674
8675 #endif
8676
8677 if( M4OSA_FALSE == pC->b_isRawWriter )
8678 {
8679 /* This allow to write PCM data to file and to encode AMR data,
8680 when output file is not RAW */
8681 if( pC->pOutputPCMfile != M4OSA_NULL )
8682 {
8683 pC->pOsaFileWritPtr->writeData(pC->pOutputPCMfile,
8684 pEncInBuffer.pTableBuffer[0], pEncInBuffer.pTableBufferSize[0]);
8685 }
8686
8687 /**
8688 * Encode the PCM audio */
8689 err = pC->pAudioEncoderGlobalFcts->pFctStep(pC->pAudioEncCtxt,
8690 &pEncInBuffer, &pEncOutBuffer);
8691
8692 if( M4NO_ERROR != err )
8693 {
8694 M4OSA_TRACE1_1(
8695 "M4MCS_intAudioTranscoding(): pAudioEncoderGlobalFcts->pFctStep returns 0x%x",
8696 err);
8697 return err;
8698 }
8699
8700 /* update data consumed into encoder buffer in after encoding (empty) */
8701 pC->pPosInAudioEncoderBuffer = M4OSA_NULL;
8702
8703 /**
8704 * Set AU cts and size */
8705 pC->WriterAudioAU.size =
8706 pEncOutBuffer.
8707 pTableBufferSize[0]; /**< Get the size of encoded data */
8708 pC->WriterAudioAU.CTS += frameTimeDelta;
8709
8710 /**
8711 * Update duration of the encoded AU */
8712 pC->m_audioAUDuration =
8713 ( frameTimeDelta * 1000) / pC->WriterAudioStream.timeScale;
8714
8715 /**
8716 * Write the encoded AU to the output file */
8717 pC->uiAudioAUCount++;
8718 err = pC->pWriterDataFcts->pProcessAU(pC->pWriterContext,
8719 M4MCS_WRITER_AUDIO_STREAM_ID, &pC->WriterAudioAU);
8720
8721 if( M4NO_ERROR != err )
8722 {
8723 M4OSA_TRACE1_1(
8724 "M4MCS_intAudioTranscoding(): pWriterDataFcts->pProcessAU(Audio) returns 0x%x",
8725 err);
8726 return err;
8727 }
8728 }
8729 else
8730 {
8731 /* update data consumed into encoder buffer in after encoding (empty) */
8732 pC->pPosInAudioEncoderBuffer = M4OSA_NULL;
8733
8734 pC->WriterAudioAU.dataAddress =
8735 (M4OSA_MemAddr32)
8736 pEncoderInput; /* will be converted back to u8* in file write */
8737 pC->WriterAudioAU.size = pC->audioEncoderGranularity;
8738 pC->uiAudioAUCount++;
8739
8740 err = pC->pWriterDataFcts->pProcessAU(pC->pWriterContext,
8741 M4MCS_WRITER_AUDIO_STREAM_ID, &pC->WriterAudioAU);
8742
8743 if( M4NO_ERROR != err )
8744 {
8745 M4OSA_TRACE1_1(
8746 "M4MCS_intAudioTranscoding(): pWriterDataFcts->pProcessAU(Audio) returns 0x%x",
8747 err);
8748 return err;
8749 }
8750 }
8751
8752 /* _______________ */
8753 /*| |*/
8754 /*| ONE PASS DONE |*/
8755 /*|_______________|*/
8756
8757 m4mcs_intaudiotranscoding_end:
8758
8759 /**
8760 * Return with no error */
8761 M4OSA_TRACE3_0("M4MCS_intAudioTranscoding(): returning M4NO_ERROR");
8762 return M4NO_ERROR;
8763 }
8764
8765 /**
8766 ******************************************************************************
8767 * M4OSA_ERR M4MCS_intReallocTemporaryAU(M4OSA_MemAddr8* addr, M4OSA_UInt32 newSize)
8768 * Used only in case of 3GP constant memory reader, to be able to realloc temporary AU
8769 * because max AU size can be reevaluated during reading
8770 * @return M4NO_ERROR: No error
8771 ******************************************************************************
8772 */
M4MCS_intReallocTemporaryAU(M4OSA_MemAddr8 * addr,M4OSA_UInt32 newSize)8773 static M4OSA_ERR M4MCS_intReallocTemporaryAU( M4OSA_MemAddr8 *addr,
8774 M4OSA_UInt32 newSize )
8775 {
8776 if( *addr != M4OSA_NULL )
8777 {
8778 free(*addr);
8779 *addr = (M4OSA_MemAddr8)M4OSA_32bitAlignedMalloc(newSize, M4MCS,
8780 (M4OSA_Char *)"Reallocation of temporary AU buffer");
8781
8782 if( *addr == M4OSA_NULL )
8783 {
8784 return M4ERR_ALLOC;
8785 }
8786 }
8787
8788 return M4NO_ERROR;
8789 }
8790
8791 /**
8792 ******************************************************************************
8793 * M4OSA_ERR M4MCS_intVideoNullEncoding(M4MCS_InternalContext* pC)
8794 * @author Alexis Vapillon (NXP Software Vision)
8795 * @return M4NO_ERROR: No error
8796 ******************************************************************************
8797 */
M4MCS_intVideoNullEncoding(M4MCS_InternalContext * pC)8798 static M4OSA_ERR M4MCS_intVideoNullEncoding( M4MCS_InternalContext *pC )
8799 {
8800 M4OSA_ERR err = M4NO_ERROR;
8801 /* Duration of the AU (find the next AU duration
8802 * to obtain a more precise video end cut)
8803 */
8804 M4OSA_UInt32 videoAUDuration = 0;
8805
8806 M4OSA_MemAddr8 WritebufferAdd = M4OSA_NULL;
8807 M4OSA_Int32 lastdecodedCTS = 0;
8808 M4_AccessUnit lReaderVideoAU; /**< Read video access unit */
8809
8810 if( pC->novideo )
8811 return M4NO_ERROR;
8812
8813 /* H.264 Trimming */
8814 if( ( ( pC->bH264Trim == M4OSA_TRUE)
8815 && (pC->uiVideoAUCount < pC->m_pInstance->clip_sps.num_ref_frames)
8816 && (pC->uiBeginCutTime > 0))
8817 || (( pC->uiVideoAUCount == 0) && (pC->uiBeginCutTime > 0)) )
8818 {
8819 err = M4MCS_intVideoTranscoding(pC);
8820 return err;
8821 }
8822
8823
8824 if((pC->bLastDecodedFrameCTS == M4OSA_FALSE) && (pC->uiBeginCutTime > 0))
8825 {
8826 // StageFright encoder does prefetch, the one frame we requested will not be written until
8827 // the encoder is closed, so do it now rather than in MCS_close
8828 if( ( M4NO_ERROR != err)
8829 || (M4MCS_kEncoderRunning != pC->encoderState) )
8830 {
8831 M4OSA_TRACE1_2(
8832 "!!! M4MCS_intVideoNullEncoding ERROR : M4MCS_intVideoTranscoding "
8833 "returns 0x%X w/ encState=%d", err, pC->encoderState);
8834
8835 return err;
8836 }
8837
8838 /* Stop and close the encoder now to flush the frame (prefetch) */
8839 if( pC->pVideoEncoderGlobalFcts->pFctStop != M4OSA_NULL )
8840 {
8841 err = pC->pVideoEncoderGlobalFcts->pFctStop(pC->pViEncCtxt);
8842
8843 if( M4NO_ERROR != err )
8844 {
8845 M4OSA_TRACE1_1(
8846 "!!! M4MCS_intVideoNullEncoding ERROR : encoder stop returns 0x%X",
8847 err);
8848 return err;
8849 }
8850 }
8851 pC->encoderState = M4MCS_kEncoderStopped;
8852 err = pC->pVideoEncoderGlobalFcts->pFctClose(pC->pViEncCtxt);
8853
8854 if( M4NO_ERROR != err )
8855 {
8856 M4OSA_TRACE1_1(
8857 "!!! M4MCS_intVideoNullEncoding ERROR : encoder close returns 0x%X",
8858 err);
8859 return err;
8860 }
8861 pC->encoderState = M4MCS_kEncoderClosed;
8862 }
8863
8864
8865 if ((pC->EncodingVideoFormat = M4ENCODER_kNULL)
8866 && (pC->bLastDecodedFrameCTS == M4OSA_FALSE)
8867 && (pC->uiBeginCutTime > 0)) {
8868
8869 pC->bLastDecodedFrameCTS = M4OSA_TRUE;
8870 err = pC->m_pVideoDecoder->m_pFctGetOption(pC->pViDecCtxt,
8871 M4DECODER_kOptionID_AVCLastDecodedFrameCTS, &lastdecodedCTS);
8872
8873 if (M4NO_ERROR != err) {
8874 M4OSA_TRACE1_1(
8875 "M4MCS_intVideoNullEncoding: m_pVideoDecoder->m_pFctGetOption returns 0x%x!",
8876 err);
8877 return err;
8878 }
8879 /* Do not need video decoder any more, need to destroy it. Otherwise it
8880 * will call reader function which will cause frame lost during triming,
8881 * since the 3gp reader is shared between MCS and decoder.*/
8882 if (M4OSA_NULL != pC->pViDecCtxt) {
8883 err = pC->m_pVideoDecoder->m_pFctDestroy(pC->pViDecCtxt);
8884 pC->pViDecCtxt = M4OSA_NULL;
8885
8886 if (M4NO_ERROR != err) {
8887 M4OSA_TRACE1_1(
8888 "M4MCS_intVideoNullEncoding: decoder pFctDestroy returns 0x%x",
8889 err);
8890 return err;
8891 }
8892 }
8893
8894 err = pC->m_pReader->m_pFctJump(pC->pReaderContext,
8895 (M4_StreamHandler *)pC->pReaderVideoStream, &lastdecodedCTS);
8896
8897 if (M4NO_ERROR != err) {
8898 M4OSA_TRACE1_1(
8899 "M4MCS_intVideoNullEncoding: m_pFctJump(V) returns 0x%x!",
8900 err);
8901 return err;
8902 }
8903
8904
8905 /* Initializes an access Unit */
8906
8907 err = pC->m_pReader->m_pFctFillAuStruct(pC->pReaderContext,
8908 (M4_StreamHandler *)pC->pReaderVideoStream, &lReaderVideoAU);
8909
8910 if (M4NO_ERROR != err) {
8911 M4OSA_TRACE1_1(
8912 "M4MCS_intVideoNullEncoding:m_pReader->m_pFctFillAuStruct(video)\
8913 returns 0x%x", err);
8914 return err;
8915 }
8916
8917 err = pC->m_pReaderDataIt->m_pFctGetNextAu(pC->pReaderContext,
8918 (M4_StreamHandler *)pC->pReaderVideoStream, &lReaderVideoAU);
8919
8920 if (M4WAR_NO_MORE_AU == err) {
8921 M4OSA_TRACE2_0(
8922 "M4MCS_intVideoNullEncoding():\
8923 m_pReaderDataIt->m_pFctGetNextAu(video) returns M4WAR_NO_MORE_AU");
8924 /* The audio transcoding is finished */
8925 pC->VideoState = M4MCS_kStreamState_FINISHED;
8926 return err;
8927 }
8928 else if (M4NO_ERROR != err) {
8929 M4OSA_TRACE1_1(
8930 "M4MCS_intVideoNullEncoding():\
8931 m_pReaderDataIt->m_pFctGetNextAu(video) returns 0x%x",
8932 err);
8933 return err;
8934 }
8935
8936 M4OSA_TRACE1_1(
8937 "### [TS_CHECK] M4MCS_intVideoNullEncoding video AU CTS: %d ",
8938 lReaderVideoAU.m_CTS);
8939
8940
8941 }
8942
8943
8944 pC->bLastDecodedFrameCTS = M4OSA_TRUE;
8945
8946
8947 /* Find the next AU duration to obtain a more precise video end cut*/
8948 /**
8949 * Initializes a new AU if needed */
8950
8951 if (pC->ReaderVideoAU1.m_structSize == 0) {
8952 /**
8953 * Initializes an access Unit */
8954 err = pC->m_pReader->m_pFctFillAuStruct(pC->pReaderContext,
8955 (M4_StreamHandler *)pC->pReaderVideoStream,
8956 &pC->ReaderVideoAU1);
8957
8958 if (M4NO_ERROR != err) {
8959 M4OSA_TRACE1_1(
8960 "M4MCS_open(): m_pReader->m_pFctFillAuStruct(video) returns 0x%x",
8961 err);
8962 return err;
8963 }
8964
8965 pC->m_pDataVideoAddress1 =
8966 (M4OSA_MemAddr8)M4OSA_32bitAlignedMalloc(pC->ReaderVideoAU1.m_maxsize, M4MCS,
8967 (M4OSA_Char *)"Temporary video AU1 buffer");
8968
8969 if (pC->m_pDataVideoAddress1 == M4OSA_NULL) {
8970 M4OSA_TRACE1_0("M4MCS_intVideoNullEncoding(): allocation error");
8971 return M4ERR_ALLOC;
8972 }
8973
8974 err = pC->m_pReaderDataIt->m_pFctGetNextAu(pC->pReaderContext,
8975 (M4_StreamHandler *)pC->pReaderVideoStream,
8976 &pC->ReaderVideoAU1);
8977
8978 if( M4WAR_NO_MORE_AU == err )
8979 {
8980 M4OSA_TRACE2_0(
8981 "M4MCS_intVideoNullEncoding():\
8982 m_pReaderDataIt->m_pFctGetNextAu(video) returns M4WAR_NO_MORE_AU");
8983 /* The audio transcoding is finished */
8984 pC->VideoState = M4MCS_kStreamState_FINISHED;
8985 return err;
8986 }
8987 else if( M4NO_ERROR != err )
8988 {
8989 M4OSA_TRACE1_1(
8990 "M4MCS_intVideoNullEncoding(): m_pReaderDataIt->m_pFctGetNextAu(video)\
8991 returns 0x%x", err);
8992 return err;
8993 }
8994
8995 if( pC->ReaderVideoAU1.m_maxsize
8996 > pC->pReaderVideoStream->m_basicProperties.m_maxAUSize )
8997 {
8998 /* Constant memory reader case, we need to reallocate the temporary buffers */
8999 M4MCS_intReallocTemporaryAU((M4OSA_MemAddr8
9000 *) &(pC->m_pDataVideoAddress1), pC->ReaderVideoAU1.m_maxsize);
9001 /* pC->m_pDataVideoAddress1
9002 and pC->m_pDataVideoAddress2 must be reallocated at the same time */
9003 /* because pC->pReaderVideoStream->m_basicProperties.m_maxAUSize take maximum value.
9004 Then the test "if(pC->ReaderVideoAU?.m_maxsize > pC->pReaderVideoStream->
9005 m_basicProperties.m_maxAUSize)" is never true */
9006 /* and the size of the second buffer is never changed. */
9007 M4MCS_intReallocTemporaryAU((M4OSA_MemAddr8
9008 *) &(pC->m_pDataVideoAddress2), pC->ReaderVideoAU1.m_maxsize);
9009 /* pC->m_pDataVideoAddress1 and
9010 pC->m_pDataVideoAddress2 must be reallocated at the same time */
9011 /* Update stream properties */
9012 pC->pReaderVideoStream->m_basicProperties.m_maxAUSize =
9013 pC->ReaderVideoAU1.m_maxsize;
9014 }
9015 memcpy((void *)pC->m_pDataVideoAddress1,
9016 (void *)pC->ReaderVideoAU1.m_dataAddress,
9017 pC->ReaderVideoAU1.m_size);
9018 }
9019
9020 if( pC->ReaderVideoAU2.m_structSize == 0 )
9021 {
9022 /**
9023 * Initializes an access Unit */
9024 err = pC->m_pReader->m_pFctFillAuStruct(pC->pReaderContext,
9025 (M4_StreamHandler *)pC->pReaderVideoStream,
9026 &pC->ReaderVideoAU2);
9027
9028 if( M4NO_ERROR != err )
9029 {
9030 M4OSA_TRACE1_1(
9031 "M4MCS_open(): m_pReader->m_pFctFillAuStruct(video) returns 0x%x",
9032 err);
9033 return err;
9034 }
9035 pC->m_pDataVideoAddress2 =
9036 (M4OSA_MemAddr8)M4OSA_32bitAlignedMalloc(pC->ReaderVideoAU2.m_maxsize, M4MCS,
9037 (M4OSA_Char *)"Temporary video AU buffer");
9038
9039 if( pC->m_pDataVideoAddress2 == M4OSA_NULL )
9040 {
9041 M4OSA_TRACE1_0("M4MCS_intVideoNullEncoding(): allocation error");
9042 return M4ERR_ALLOC;
9043 }
9044 }
9045 /**
9046 * Read the next video AU in the input file */
9047 if( pC->ReaderVideoAU2.m_CTS > pC->ReaderVideoAU1.m_CTS )
9048 {
9049 memcpy((void *) &pC->ReaderVideoAU,
9050 (void *) &pC->ReaderVideoAU2, sizeof(M4_AccessUnit));
9051 err = pC->m_pReaderDataIt->m_pFctGetNextAu(pC->pReaderContext,
9052 (M4_StreamHandler *)pC->pReaderVideoStream,
9053 &pC->ReaderVideoAU1);
9054
9055 if( pC->ReaderVideoAU1.m_maxsize
9056 > pC->pReaderVideoStream->m_basicProperties.m_maxAUSize )
9057 {
9058 /* Constant memory reader case, we need to reallocate the temporary buffers */
9059 M4MCS_intReallocTemporaryAU((M4OSA_MemAddr8
9060 *) &(pC->m_pDataVideoAddress1), pC->ReaderVideoAU1.m_maxsize);
9061 /* pC->m_pDataVideoAddress1 and
9062 pC->m_pDataVideoAddress2 must be reallocated at the same time */
9063 /* because pC->pReaderVideoStream->m_basicProperties.m_maxAUSize take maximum value.
9064 Then the test "if(pC->ReaderVideoAU?.m_maxsize > pC->pReaderVideoStream->
9065 m_basicProperties.m_maxAUSize)" is never true */
9066 /* and the size of the second buffer is never changed. */
9067 M4MCS_intReallocTemporaryAU((M4OSA_MemAddr8
9068 *) &(pC->m_pDataVideoAddress2), pC->ReaderVideoAU1.m_maxsize);
9069 /* pC->m_pDataVideoAddress1 and
9070 pC->m_pDataVideoAddress2 must be reallocated at the same time */
9071 /* Update stream properties */
9072 pC->pReaderVideoStream->m_basicProperties.m_maxAUSize =
9073 pC->ReaderVideoAU1.m_maxsize;
9074 }
9075 memcpy((void *)pC->m_pDataVideoAddress1,
9076 (void *)pC->ReaderVideoAU1.m_dataAddress,
9077 pC->ReaderVideoAU1.m_size);
9078 videoAUDuration = pC->ReaderVideoAU1.m_CTS - pC->ReaderVideoAU2.m_CTS;
9079 pC->ReaderVideoAU.m_dataAddress = pC->m_pDataVideoAddress2;
9080 }
9081 else
9082 {
9083 memcpy((void *) &pC->ReaderVideoAU,
9084 (void *) &pC->ReaderVideoAU1, sizeof(M4_AccessUnit));
9085 err = pC->m_pReaderDataIt->m_pFctGetNextAu(pC->pReaderContext,
9086 (M4_StreamHandler *)pC->pReaderVideoStream,
9087 &pC->ReaderVideoAU2);
9088
9089 if( pC->ReaderVideoAU2.m_maxsize
9090 > pC->pReaderVideoStream->m_basicProperties.m_maxAUSize )
9091 {
9092 /* Constant memory reader case, we need to reallocate the temporary buffers */
9093 M4MCS_intReallocTemporaryAU((M4OSA_MemAddr8
9094 *) &(pC->m_pDataVideoAddress2), pC->ReaderVideoAU2.m_maxsize);
9095 /* pC->m_pDataVideoAddress1 and
9096 pC->m_pDataVideoAddress2 must be reallocated at the same time */
9097 /* because pC->pReaderVideoStream->m_basicProperties.m_maxAUSize take maximum value.
9098 Then the test "if(pC->ReaderVideoAU?.m_maxsize > pC->pReaderVideoStream->
9099 m_basicProperties.m_maxAUSize)" is never true */
9100 /* and the size of the second buffer is never changed. */
9101 M4MCS_intReallocTemporaryAU((M4OSA_MemAddr8
9102 *) &(pC->m_pDataVideoAddress1), pC->ReaderVideoAU2.m_maxsize);
9103 /* pC->m_pDataVideoAddress1 and
9104 pC->m_pDataVideoAddress2 must be reallocated at the same time */
9105 /* Update stream properties */
9106 pC->pReaderVideoStream->m_basicProperties.m_maxAUSize =
9107 pC->ReaderVideoAU2.m_maxsize;
9108 }
9109 memcpy((void *)pC->m_pDataVideoAddress2,
9110 (void *)pC->ReaderVideoAU2.m_dataAddress,
9111 pC->ReaderVideoAU2.m_size);
9112 videoAUDuration = pC->ReaderVideoAU2.m_CTS - pC->ReaderVideoAU1.m_CTS;
9113 pC->ReaderVideoAU.m_dataAddress = pC->m_pDataVideoAddress1;
9114 }
9115
9116 if( M4WAR_NO_MORE_AU == err )
9117 {
9118 M4OSA_TRACE2_0(
9119 "M4MCS_intVideoNullEncoding():\
9120 m_pReaderDataIt->m_pFctGetNextAu(video) returns M4WAR_NO_MORE_AU");
9121 /* The video transcoding is finished */
9122 pC->VideoState = M4MCS_kStreamState_FINISHED;
9123 return err;
9124 }
9125 else if( M4NO_ERROR != err )
9126 {
9127 M4OSA_TRACE1_1(
9128 "M4MCS_intVideoNullEncoding(): m_pReaderDataIt->m_pFctGetNextAu(Video) returns 0x%x",
9129 err);
9130 return err;
9131 }
9132 else
9133 {
9134 /**
9135 * Prepare the writer AU */
9136 err = pC->pWriterDataFcts->pStartAU(pC->pWriterContext,
9137 M4MCS_WRITER_VIDEO_STREAM_ID, &pC->WriterVideoAU);
9138
9139 if( M4NO_ERROR != err )
9140 {
9141 M4OSA_TRACE1_1(
9142 "M4MCS_intVideoNullEncoding(): pWriterDataFcts->pStartAU(Video) returns 0x%x",
9143 err);
9144 return err;
9145 }
9146 /**
9147 * Copy video data from reader AU to writer AU */
9148 M4OSA_TRACE3_1(
9149 "M4MCS_intVideoNullEncoding(): Copying video AU: size=%d",
9150 pC->ReaderVideoAU.m_size);
9151 /* + CRLV6775 -H.264 Trimming */
9152 if( M4OSA_TRUE == pC->bH264Trim )
9153 {
9154 if( pC->H264MCSTempBufferSize
9155 < (pC->ReaderVideoAU.m_size + 2048) )
9156 {
9157 pC->H264MCSTempBufferSize =
9158 (pC->ReaderVideoAU.m_size + 2048);
9159
9160 if( pC->H264MCSTempBuffer != M4OSA_NULL )
9161 {
9162 free(pC->H264MCSTempBuffer);
9163 }
9164 pC->H264MCSTempBuffer =
9165 (M4OSA_UInt8 *)M4OSA_32bitAlignedMalloc(pC->H264MCSTempBufferSize,
9166 M4MCS, (M4OSA_Char *)"pC->H264MCSTempBuffer");
9167
9168 if( pC->H264MCSTempBuffer == M4OSA_NULL )
9169 {
9170 M4OSA_TRACE1_0(
9171 "M4MCS_intVideoNullEncoding(): allocation error");
9172 return M4ERR_ALLOC;
9173 }
9174 }
9175
9176 pC->H264MCSTempBufferDataSize = pC->H264MCSTempBufferSize;
9177
9178 err = H264MCS_ProcessNALU(pC->m_pInstance,
9179 (M4OSA_UInt8 *)pC->ReaderVideoAU.m_dataAddress,
9180 pC->ReaderVideoAU.m_size, pC->H264MCSTempBuffer,
9181 (M4OSA_Int32 *)&pC->H264MCSTempBufferDataSize);
9182
9183 if( pC->m_pInstance->is_done == 1 )
9184 {
9185 M4MCS_convetFromByteStreamtoNALStream(
9186 (M4OSA_UInt8 *)pC->ReaderVideoAU.m_dataAddress ,
9187 pC->ReaderVideoAU.m_size);
9188
9189 memcpy((void *)pC->WriterVideoAU.dataAddress,
9190 (void *)(pC->ReaderVideoAU.m_dataAddress + 4),
9191 pC->ReaderVideoAU.m_size - 4);
9192 pC->WriterVideoAU.size = pC->ReaderVideoAU.m_size - 4;
9193 WritebufferAdd =
9194 (M4OSA_MemAddr8)pC->WriterVideoAU.dataAddress;
9195 }
9196 else
9197 {
9198 memcpy((void *)pC->WriterVideoAU.dataAddress,
9199 (void *)(pC->H264MCSTempBuffer + 4),
9200 pC->H264MCSTempBufferDataSize - 4);
9201 pC->WriterVideoAU.size = pC->H264MCSTempBufferDataSize - 4;
9202 WritebufferAdd =
9203 (M4OSA_MemAddr8)pC->WriterVideoAU.dataAddress;
9204 }
9205 }
9206 /* H.264 Trimming */
9207 else
9208 {
9209 memcpy((void *)pC->WriterVideoAU.dataAddress,
9210 (void *)pC->ReaderVideoAU.m_dataAddress,
9211 pC->ReaderVideoAU.m_size);
9212 pC->WriterVideoAU.size = pC->ReaderVideoAU.m_size;
9213 }
9214 /**
9215 * Convert CTS unit from milliseconds to timescale */
9216 pC->WriterVideoAU.CTS =
9217 (M4OSA_Time)((( pC->ReaderVideoAU.m_CTS - pC->dViDecStartingCts)
9218 * (pC->WriterVideoStream.timeScale / 1000.0)));
9219 pC->WriterVideoAU.nbFrag = 0;
9220 pC->WriterVideoAU.attribute = pC->ReaderVideoAU.m_attribute;
9221
9222 M4OSA_TRACE3_1("M4MCS_intVideoNullEncoding(): video AU: CTS=%d ms",
9223 pC->WriterVideoAU.CTS);
9224
9225 /**
9226 * Write it to the output file */
9227 pC->uiVideoAUCount++;
9228 err = pC->pWriterDataFcts->pProcessAU(pC->pWriterContext,
9229 M4MCS_WRITER_VIDEO_STREAM_ID, &pC->WriterVideoAU);
9230
9231 if( M4NO_ERROR != err )
9232 {
9233 M4OSA_TRACE1_1(
9234 "M4MCS_intVideoNullEncoding(): pWriterDataFcts->pProcessAU(Video) returns 0x%x",
9235 err);
9236 return err;
9237 }
9238 /* + CRLV6775 -H.264 Trimming */
9239 if( M4OSA_TRUE == pC->bH264Trim )
9240 {
9241 if( pC->m_pInstance->is_done == 1 )
9242 {
9243 memcpy((void *)(WritebufferAdd - 4),
9244 (void *)(pC->ReaderVideoAU.m_dataAddress), 4);
9245 }
9246 else
9247 {
9248 memcpy((void *)(WritebufferAdd - 4),
9249 (void *)(pC->H264MCSTempBuffer), 4);
9250 }
9251 } /* H.264 Trimming */
9252 }
9253 /**
9254 * Check for end cut. */
9255 /* Bug fix 11/12/2008: We absolutely want to have less or same video duration ->
9256 (2*videoAUDuration) to have a more precise end cut*/
9257 if( pC->ReaderVideoAU.m_CTS + (2 *videoAUDuration) > pC->uiEndCutTime )
9258 {
9259 pC->VideoState = M4MCS_kStreamState_FINISHED;
9260 }
9261
9262 /**
9263 * Return with no error */
9264 M4OSA_TRACE3_0("M4MCS_intVideoNullEncoding(): returning M4NO_ERROR");
9265 return M4NO_ERROR;
9266 }
9267
9268 /**
9269 ******************************************************************************
9270 * M4OSA_ERR M4MCS_intVideoTranscoding(M4MCS_InternalContext* pC)
9271 * @author Alexis Vapillon (NXP Software Vision)
9272 * @return M4NO_ERROR: No error
9273 ******************************************************************************
9274 */
M4MCS_intVideoTranscoding(M4MCS_InternalContext * pC)9275 static M4OSA_ERR M4MCS_intVideoTranscoding( M4MCS_InternalContext *pC )
9276 {
9277 M4OSA_ERR err = M4NO_ERROR;
9278 M4_MediaTime mtTranscodedTime = 0.0;
9279 M4ENCODER_FrameMode FrameMode;
9280 M4OSA_Int32 derive = 0;
9281
9282 /**
9283 * Get video CTS to decode */
9284 mtTranscodedTime = pC->dViDecCurrentCts;
9285 FrameMode = M4ENCODER_kNormalFrame;
9286
9287 /**
9288 * Decode video */
9289 M4OSA_TRACE3_1(
9290 "M4MCS_intVideoTranscoding(): Calling m_pVideoDecoder->m_pFctDecode(%.2f)",
9291 mtTranscodedTime);
9292 pC->isRenderDup = M4OSA_FALSE;
9293 err = pC->m_pVideoDecoder->m_pFctDecode(pC->pViDecCtxt, &mtTranscodedTime,
9294 M4OSA_FALSE, 0);
9295
9296 if( M4WAR_NO_MORE_AU == err )
9297 {
9298 FrameMode =
9299 M4ENCODER_kLastFrame; /**< We will give this value to the encoder to
9300 ask for the end of the encoding */
9301 pC->VideoState = M4MCS_kStreamState_FINISHED;
9302 }
9303 else if( err == M4WAR_VIDEORENDERER_NO_NEW_FRAME )
9304 {
9305 M4OSA_TRACE2_0("Decoding output the same frame as before 3");
9306 pC->isRenderDup = M4OSA_TRUE;
9307 }
9308 else if( M4NO_ERROR != err )
9309 {
9310 M4OSA_TRACE1_1(
9311 "M4MCS_intVideoTranscoding(): m_pVideoDecoder->m_pFctDecode returns 0x%x!",
9312 err);
9313 return err;
9314 }
9315
9316 /**
9317 * Check for end cut.
9318 * We must check here if the end cut is reached, because in that case we must
9319 * call the last encode step (-> bLastFrame set to true) */
9320 if( ( pC->dViDecCurrentCts + pC->dCtsIncrement ) >= (pC->uiEndCutTime
9321 + M4MCS_ABS(pC->dViDecStartingCts - pC->uiBeginCutTime)) )
9322 {
9323 FrameMode =
9324 M4ENCODER_kLastFrame; /**< We will give this value to the encoder to
9325 ask for the end of the encoding */
9326 pC->VideoState = M4MCS_kStreamState_FINISHED;
9327 derive = (M4OSA_Int32)(( pC->dViDecCurrentCts + pC->dCtsIncrement + 0.5)
9328 - (pC->uiEndCutTime
9329 + M4MCS_ABS(pC->dViDecStartingCts - pC->uiBeginCutTime)));
9330 }
9331
9332 /* Update starting CTS to have a more precise value (
9333 the begin cut is not a real CTS)*/
9334 if( pC->uiVideoAUCount == 0 )
9335 {
9336 pC->dViDecStartingCts = mtTranscodedTime;
9337 pC->dViDecCurrentCts = pC->dViDecStartingCts;
9338 }
9339
9340 /**
9341 * Encode video */
9342 M4OSA_TRACE3_1(
9343 "M4MCS_intVideoTranscoding(): Calling pVideoEncoderGlobalFcts->pFctEncode with videoCts\
9344 = %.2f",pC->ReaderVideoAU.m_CTS);
9345 pC->uiVideoAUCount++;
9346 /* update the given duration (the begin cut is not a real CTS)*/
9347 err = pC->pVideoEncoderGlobalFcts->pFctEncode(pC->pViEncCtxt, M4OSA_NULL,
9348 (pC->dViDecCurrentCts - pC->dViDecStartingCts - (derive >> 1)),
9349 FrameMode);
9350
9351 return err;
9352 }
9353
9354 /**
9355 ******************************************************************************
9356 * M4OSA_ERR M4MCS_intGetInputClipProperties(M4MCS_InternalContext* pContext)
9357 * @author Dounya Manai (NXP Software Vision)
9358 * @brief Retrieve the properties of the audio and video streams from the input file.
9359 * @param pContext (IN) MCS context
9360 * @return M4NO_ERROR: No error
9361 * @return M4ERR_PARAMETER: pContext is M4OSA_NULL (If Debug Level >= 2)
9362 ******************************************************************************
9363 */
M4MCS_intGetInputClipProperties(M4MCS_InternalContext * pC)9364 static M4OSA_ERR M4MCS_intGetInputClipProperties( M4MCS_InternalContext *pC )
9365 {
9366 M4DECODER_MPEG4_DecoderConfigInfo DecConfInfo;
9367 M4READER_3GP_H263Properties H263prop;
9368 M4OSA_ERR err;
9369 M4OSA_UInt32 videoBitrate;
9370 M4DECODER_VideoSize videoSize;
9371 M4_AACType iAacType = 0;
9372
9373 /**
9374 * Check input parameters */
9375 M4OSA_DEBUG_IF2(M4OSA_NULL == pC, M4ERR_PARAMETER,
9376 "M4MCS_intGetInputClipProperties: pC is M4OSA_NULL");
9377
9378 /**
9379 * Reset common characteristics */
9380 pC->InputFileProperties.bAnalysed = M4OSA_FALSE;
9381 pC->InputFileProperties.FileType = 0;
9382 pC->InputFileProperties.Version[0] = M4VIDEOEDITING_VERSION_MAJOR;
9383 pC->InputFileProperties.Version[1] = M4VIDEOEDITING_VERSION_MINOR;
9384 pC->InputFileProperties.Version[2] = M4VIDEOEDITING_VERSION_REVISION;
9385 pC->InputFileProperties.uiClipDuration = 0;
9386
9387 memset((void *) &pC->InputFileProperties.ftyp,
9388 0, sizeof(M4VIDEOEDITING_FtypBox));
9389
9390 /**
9391 * Reset video characteristics */
9392 pC->InputFileProperties.VideoStreamType = M4VIDEOEDITING_kNoneVideo;
9393 pC->InputFileProperties.uiClipVideoDuration = 0;
9394 pC->InputFileProperties.uiVideoBitrate = 0;
9395 pC->InputFileProperties.uiVideoMaxAuSize = 0;
9396 pC->InputFileProperties.uiVideoWidth = 0;
9397 pC->InputFileProperties.uiVideoHeight = 0;
9398 pC->InputFileProperties.uiVideoTimeScale = 0;
9399 pC->InputFileProperties.fAverageFrameRate = 0.0;
9400 pC->InputFileProperties.uiVideoLevel =
9401 M4VIDEOEDITING_VIDEO_UNKNOWN_LEVEL;
9402 pC->InputFileProperties.uiVideoProfile =
9403 M4VIDEOEDITING_VIDEO_UNKNOWN_PROFILE;
9404 pC->InputFileProperties.bMPEG4dataPartition = M4OSA_FALSE;
9405 pC->InputFileProperties.bMPEG4rvlc = M4OSA_FALSE;
9406 pC->InputFileProperties.bMPEG4resynchMarker = M4OSA_FALSE;
9407
9408 /**
9409 * Reset audio characteristics */
9410 pC->InputFileProperties.AudioStreamType = M4VIDEOEDITING_kNoneAudio;
9411 pC->InputFileProperties.uiClipAudioDuration = 0;
9412 pC->InputFileProperties.uiAudioBitrate = 0;
9413 pC->InputFileProperties.uiAudioMaxAuSize = 0;
9414 pC->InputFileProperties.uiNbChannels = 0;
9415 pC->InputFileProperties.uiSamplingFrequency = 0;
9416 pC->InputFileProperties.uiExtendedSamplingFrequency = 0;
9417 pC->InputFileProperties.uiDecodedPcmSize = 0;
9418
9419 /* Reset compatibility chart (not used in MCS) */
9420 pC->InputFileProperties.bVideoIsEditable = M4OSA_FALSE;
9421 pC->InputFileProperties.bAudioIsEditable = M4OSA_FALSE;
9422 pC->InputFileProperties.bVideoIsCompatibleWithMasterClip = M4OSA_FALSE;
9423 pC->InputFileProperties.bAudioIsCompatibleWithMasterClip = M4OSA_FALSE;
9424
9425 /**
9426 * Video stream properties */
9427 if( M4OSA_NULL != pC->pReaderVideoStream )
9428 {
9429 switch( pC->pReaderVideoStream->m_basicProperties.m_streamType )
9430 {
9431 case M4DA_StreamTypeVideoMpeg4:
9432 pC->InputFileProperties.VideoStreamType = M4VIDEOEDITING_kMPEG4;
9433 break;
9434
9435 case M4DA_StreamTypeVideoH263:
9436 pC->InputFileProperties.VideoStreamType = M4VIDEOEDITING_kH263;
9437 break;
9438
9439 case M4DA_StreamTypeVideoMpeg4Avc:
9440 pC->InputFileProperties.VideoStreamType = M4VIDEOEDITING_kH264;
9441 break;
9442
9443 case M4DA_StreamTypeUnknown:
9444 default:
9445 pC->InputFileProperties.VideoStreamType =
9446 M4VIDEOEDITING_kUnsupportedVideo;
9447 break;
9448 }
9449
9450 /* if bitrate not available retrieve an estimation of the overall bitrate */
9451 pC->InputFileProperties.uiVideoBitrate =
9452 pC->pReaderVideoStream->m_basicProperties.m_averageBitRate;
9453
9454 if( 0 == pC->InputFileProperties.uiVideoBitrate )
9455 {
9456 pC->m_pReader->m_pFctGetOption(pC->pReaderContext,
9457 M4READER_kOptionID_Bitrate, &videoBitrate);
9458
9459 if( M4OSA_NULL != pC->pReaderAudioStream )
9460 {
9461 /* we get the overall bitrate, substract the audio bitrate if any */
9462 videoBitrate -=
9463 pC->pReaderAudioStream->m_basicProperties.m_averageBitRate;
9464 }
9465 pC->InputFileProperties.uiVideoBitrate = videoBitrate;
9466 }
9467
9468 /**
9469 * Retrieve the Profile & Level */
9470 if( ( M4VIDEOEDITING_kH263 != pC->InputFileProperties.VideoStreamType)
9471 && (M4VIDEOEDITING_kH264
9472 != pC->InputFileProperties.VideoStreamType) )
9473 {
9474 /* Use the DSI parsing function from the external video shell decoder.
9475 See the comments in M4VSS3GPP_ClipAnalysis.c, it's pretty much the
9476 same issue. */
9477
9478 err = M4DECODER_EXTERNAL_ParseVideoDSI(pC->pReaderVideoStream->
9479 m_basicProperties.m_pDecoderSpecificInfo,
9480 pC->pReaderVideoStream->
9481 m_basicProperties.m_decoderSpecificInfoSize,
9482 &DecConfInfo, &videoSize);
9483
9484 if( M4NO_ERROR != err )
9485 {
9486 M4OSA_TRACE1_1(
9487 "M4MCS_intGetInputClipProperties():\
9488 M4DECODER_EXTERNAL_ParseVideoDSI returns 0x%08X",
9489 err);
9490 return err;
9491 }
9492
9493 pC->pReaderVideoStream->m_videoWidth = videoSize.m_uiWidth;
9494 pC->pReaderVideoStream->m_videoHeight = videoSize.m_uiHeight;
9495 pC->InputFileProperties.uiVideoTimeScale = DecConfInfo.uiTimeScale;
9496 pC->InputFileProperties.bMPEG4dataPartition =
9497 DecConfInfo.bDataPartition;
9498 pC->InputFileProperties.bMPEG4rvlc = DecConfInfo.bUseOfRVLC;
9499 pC->InputFileProperties.bMPEG4resynchMarker =
9500 DecConfInfo.uiUseOfResynchMarker;
9501
9502 err = getMPEG4ProfileAndLevel(DecConfInfo.uiProfile,
9503 &(pC->InputFileProperties.uiVideoProfile),
9504 &(pC->InputFileProperties.uiVideoLevel));
9505 if ( M4NO_ERROR != err ) {
9506 M4OSA_TRACE1_1("M4MCS_intGetInputClipProperties():\
9507 getMPEG4ProfileAndLevel returns 0x%08X", err);
9508 return err;
9509 }
9510 }
9511 else if( M4VIDEOEDITING_kH263 ==
9512 pC->InputFileProperties.VideoStreamType ) {
9513
9514 err = getH263ProfileAndLevel(pC->pReaderVideoStream->
9515 m_basicProperties.m_pDecoderSpecificInfo,
9516 pC->pReaderVideoStream->m_basicProperties.m_decoderSpecificInfoSize,
9517 &(pC->InputFileProperties.uiVideoProfile),
9518 &(pC->InputFileProperties.uiVideoLevel));
9519 if ( M4NO_ERROR != err ) {
9520 M4OSA_TRACE1_1("M4MCS_intGetInputClipProperties():\
9521 getH263ProfileAndLevel returns 0x%08X", err);
9522 return err;
9523 }
9524 /* For h263 set default timescale : 30000:1001 */
9525 pC->InputFileProperties.uiVideoTimeScale = 30000;
9526 }
9527 else if ( M4VIDEOEDITING_kH264 ==
9528 pC->InputFileProperties.VideoStreamType ) {
9529
9530 pC->InputFileProperties.uiVideoTimeScale = 30000;
9531 err = getAVCProfileAndLevel(pC->pReaderVideoStream->
9532 m_basicProperties.m_pDecoderSpecificInfo,
9533 pC->pReaderVideoStream->m_basicProperties.m_decoderSpecificInfoSize,
9534 &(pC->InputFileProperties.uiVideoProfile),
9535 &(pC->InputFileProperties.uiVideoLevel));
9536 if ( M4NO_ERROR != err ) {
9537 M4OSA_TRACE1_1("M4MCS_intGetInputClipProperties():\
9538 getAVCProfileAndLevel returns 0x%08X", err);
9539 return err;
9540 }
9541 }
9542
9543 /* Here because width x height is correct only after dsi parsing
9544 (done in create decoder) */
9545 pC->InputFileProperties.uiVideoHeight =
9546 pC->pReaderVideoStream->m_videoHeight;
9547 pC->InputFileProperties.uiVideoWidth =
9548 pC->pReaderVideoStream->m_videoWidth;
9549 pC->InputFileProperties.uiClipVideoDuration =
9550 (M4OSA_UInt32)pC->pReaderVideoStream->m_basicProperties.m_duration;
9551 pC->InputFileProperties.fAverageFrameRate =
9552 pC->pReaderVideoStream->m_averageFrameRate;
9553 pC->InputFileProperties.uiVideoMaxAuSize =
9554 pC->pReaderVideoStream->m_basicProperties.m_maxAUSize;
9555 pC->InputFileProperties.videoRotationDegrees =
9556 pC->pReaderVideoStream->videoRotationDegrees;
9557 }
9558 else
9559 {
9560 if( M4OSA_TRUE == pC->bUnsupportedVideoFound )
9561 {
9562 pC->InputFileProperties.VideoStreamType =
9563 M4VIDEOEDITING_kUnsupportedVideo;
9564 }
9565 else
9566 {
9567 pC->InputFileProperties.VideoStreamType = M4VIDEOEDITING_kNoneVideo;
9568 }
9569 }
9570
9571 /**
9572 * Audio stream properties */
9573 if( M4OSA_NULL != pC->pReaderAudioStream )
9574 {
9575 switch( pC->pReaderAudioStream->m_basicProperties.m_streamType )
9576 {
9577 case M4DA_StreamTypeAudioAmrNarrowBand:
9578 pC->InputFileProperties.AudioStreamType =
9579 M4VIDEOEDITING_kAMR_NB;
9580 break;
9581
9582 case M4DA_StreamTypeAudioAac:
9583 pC->InputFileProperties.AudioStreamType = M4VIDEOEDITING_kAAC;
9584 break;
9585
9586 case M4DA_StreamTypeAudioMp3:
9587 pC->InputFileProperties.AudioStreamType = M4VIDEOEDITING_kMP3;
9588 break;
9589
9590 case M4DA_StreamTypeAudioEvrc:
9591 pC->InputFileProperties.AudioStreamType = M4VIDEOEDITING_kEVRC;
9592 break;
9593
9594 case M4DA_StreamTypeUnknown:
9595 default:
9596 pC->InputFileProperties.AudioStreamType =
9597 M4VIDEOEDITING_kUnsupportedAudio;
9598 break;
9599 }
9600
9601 if( ( M4OSA_NULL != pC->m_pAudioDecoder)
9602 && (M4OSA_NULL == pC->pAudioDecCtxt) )
9603 {
9604 M4OSA_TRACE3_1(
9605 "M4MCS_intGetInputClipProperties: calling CreateAudioDecoder, userData= 0x%x",
9606 pC->m_pCurrentAudioDecoderUserData);
9607
9608 if( M4OSA_FALSE == pC->bExtOMXAudDecoder ) {
9609 err = M4MCS_intCheckAndGetCodecProperties(pC);
9610 }
9611 else
9612 {
9613 err = pC->m_pAudioDecoder->m_pFctCreateAudioDec(
9614 &pC->pAudioDecCtxt, pC->pReaderAudioStream,
9615 pC->m_pCurrentAudioDecoderUserData);
9616
9617 if( M4NO_ERROR == err )
9618 {
9619 /* AAC properties*/
9620 //get from Reader; temporary, till Audio decoder shell API available to
9621 //get the AAC properties
9622 pC->AacProperties.aNumChan =
9623 pC->pReaderAudioStream->m_nbChannels;
9624 pC->AacProperties.aSampFreq =
9625 pC->pReaderAudioStream->m_samplingFrequency;
9626
9627 err = pC->m_pAudioDecoder->m_pFctGetOptionAudioDec(
9628 pC->pAudioDecCtxt, M4AD_kOptionID_StreamType,
9629 (M4OSA_DataOption) &iAacType);
9630
9631 if( M4NO_ERROR != err )
9632 {
9633 M4OSA_TRACE1_1(
9634 "M4MCS_intGetInputClipProperties:\
9635 m_pAudioDecoder->m_pFctGetOptionAudioDec returns err 0x%x",
9636 err);
9637 iAacType = M4_kAAC; //set to default
9638 err = M4NO_ERROR;
9639 }
9640 else
9641 {
9642 M4OSA_TRACE3_1(
9643 "M4MCS_intGetInputClipProperties:\
9644 m_pAudioDecoder->m_pFctGetOptionAudioDec returns streamType %d",
9645 iAacType);
9646 }
9647
9648 switch( iAacType )
9649 {
9650 case M4_kAAC:
9651 pC->AacProperties.aSBRPresent = 0;
9652 pC->AacProperties.aPSPresent = 0;
9653 break;
9654
9655 case M4_kAACplus:
9656 pC->AacProperties.aSBRPresent = 1;
9657 pC->AacProperties.aPSPresent = 0;
9658 pC->AacProperties.aExtensionSampFreq =
9659 pC->pReaderAudioStream->
9660 m_samplingFrequency; //TODO
9661 break;
9662
9663 case M4_keAACplus:
9664 pC->AacProperties.aSBRPresent = 1;
9665 pC->AacProperties.aPSPresent = 1;
9666 pC->AacProperties.aExtensionSampFreq =
9667 pC->pReaderAudioStream->
9668 m_samplingFrequency; //TODO
9669 break;
9670 case M4_kUnknown:
9671 break;
9672 default:
9673 break;
9674 }
9675 M4OSA_TRACE3_2(
9676 "M4MCS_intGetInputClipProperties: AAC NBChans=%d, SamplFreq=%d",
9677 pC->AacProperties.aNumChan,
9678 pC->AacProperties.aSampFreq);
9679 }
9680 }
9681
9682 if( M4NO_ERROR != err )
9683 {
9684 M4OSA_TRACE1_1(
9685 "M4MCS_intGetInputClipProperties:\
9686 m_pAudioDecoder->m_pFctCreateAudioDec returns 0x%x",
9687 err);
9688 return err;
9689 }
9690 }
9691
9692 //EVRC
9693 if( pC->pReaderAudioStream->m_basicProperties.m_streamType
9694 == M4DA_StreamTypeAudioEvrc )
9695 {
9696 /* decoder not implemented yet, provide some default values for the null encoding */
9697 pC->pReaderAudioStream->m_nbChannels = 1;
9698 pC->pReaderAudioStream->m_samplingFrequency = 8000;
9699 }
9700
9701 /**
9702 * Bugfix P4ME00001128: With some IMTC files, the AMR bit rate is 0 kbps according
9703 the GetProperties function */
9704 if( 0 == pC->pReaderAudioStream->m_basicProperties.m_averageBitRate )
9705 {
9706 if( M4VIDEOEDITING_kAMR_NB
9707 == pC->InputFileProperties.AudioStreamType )
9708 {
9709 /**
9710 * Better returning a guessed 12.2 kbps value than a sure-to-be-false
9711 0 kbps value! */
9712 pC->InputFileProperties.uiAudioBitrate =
9713 M4VIDEOEDITING_k12_2_KBPS;
9714 }
9715 else if( M4VIDEOEDITING_kEVRC
9716 == pC->InputFileProperties.AudioStreamType )
9717 {
9718 /**
9719 * Better returning a guessed 8.5 kbps value than a sure-to-be-false
9720 0 kbps value! */
9721 pC->InputFileProperties.uiAudioBitrate =
9722 M4VIDEOEDITING_k9_2_KBPS;
9723 }
9724 else
9725 {
9726 M4OSA_UInt32 FileBitrate;
9727
9728 /* Can happen also for aac, in this case we calculate an approximative */
9729 /* value from global bitrate and video bitrate */
9730 err = pC->m_pReader->m_pFctGetOption(pC->pReaderContext,
9731 M4READER_kOptionID_Bitrate,
9732 (M4OSA_DataOption) &FileBitrate);
9733
9734 if( M4NO_ERROR != err )
9735 {
9736 M4OSA_TRACE1_1(
9737 "M4MCS_intGetInputClipProperties: M4READER_kOptionID_Bitrate returns 0x%x",
9738 err);
9739 return err;
9740 }
9741 pC->InputFileProperties.uiAudioBitrate =
9742 FileBitrate
9743 - pC->
9744 InputFileProperties.
9745 uiVideoBitrate /* normally setted to 0, if no video */;
9746 }
9747 }
9748 else
9749 {
9750 pC->InputFileProperties.uiAudioBitrate =
9751 pC->pReaderAudioStream->m_basicProperties.m_averageBitRate;
9752 }
9753
9754 pC->InputFileProperties.uiNbChannels =
9755 pC->pReaderAudioStream->m_nbChannels;
9756 pC->InputFileProperties.uiSamplingFrequency =
9757 pC->pReaderAudioStream->m_samplingFrequency;
9758 pC->InputFileProperties.uiClipAudioDuration =
9759 (M4OSA_UInt32)pC->pReaderAudioStream->m_basicProperties.m_duration;
9760 pC->InputFileProperties.uiAudioMaxAuSize =
9761 pC->pReaderAudioStream->m_basicProperties.m_maxAUSize;
9762
9763 /* Bug: with aac, value is 0 until decoder start() is called */
9764 pC->InputFileProperties.uiDecodedPcmSize =
9765 pC->pReaderAudioStream->m_byteFrameLength
9766 * pC->pReaderAudioStream->m_byteSampleSize
9767 * pC->pReaderAudioStream->m_nbChannels;
9768
9769 /* New aac properties */
9770 if( M4DA_StreamTypeAudioAac
9771 == pC->pReaderAudioStream->m_basicProperties.m_streamType )
9772 {
9773 pC->InputFileProperties.uiNbChannels = pC->AacProperties.aNumChan;
9774 pC->InputFileProperties.uiSamplingFrequency =
9775 pC->AacProperties.aSampFreq;
9776
9777 if( pC->AacProperties.aSBRPresent )
9778 {
9779 pC->InputFileProperties.AudioStreamType =
9780 M4VIDEOEDITING_kAACplus;
9781 pC->InputFileProperties.uiExtendedSamplingFrequency =
9782 pC->AacProperties.aExtensionSampFreq;
9783 }
9784
9785 if( pC->AacProperties.aPSPresent )
9786 {
9787 pC->InputFileProperties.AudioStreamType =
9788 M4VIDEOEDITING_keAACplus;
9789 }
9790 }
9791 }
9792 else
9793 {
9794 if( M4OSA_TRUE == pC->bUnsupportedAudioFound )
9795 {
9796 pC->InputFileProperties.AudioStreamType =
9797 M4VIDEOEDITING_kUnsupportedAudio;
9798 }
9799 else
9800 {
9801 pC->InputFileProperties.AudioStreamType = M4VIDEOEDITING_kNoneAudio;
9802 }
9803 }
9804
9805 /* Get 'ftyp' atom */
9806 err = pC->m_pReader->m_pFctGetOption(pC->pReaderContext,
9807 M4READER_kOptionID_3gpFtypBox, &pC->InputFileProperties.ftyp);
9808
9809 /* Analysis is successful */
9810 if( pC->InputFileProperties.uiClipVideoDuration
9811 > pC->InputFileProperties.uiClipAudioDuration )
9812 pC->InputFileProperties.uiClipDuration =
9813 pC->InputFileProperties.uiClipVideoDuration;
9814 else
9815 pC->InputFileProperties.uiClipDuration =
9816 pC->InputFileProperties.uiClipAudioDuration;
9817
9818 pC->InputFileProperties.FileType = pC->InputFileType;
9819 pC->InputFileProperties.bAnalysed = M4OSA_TRUE;
9820
9821 return M4NO_ERROR;
9822 }
9823
9824 /**
9825 ******************************************************************************
9826 * M4OSA_UInt32 M4MCS_intGetFrameSize_AMRNB(M4OSA_MemAddr8 pAudioFrame)
9827 * @brief Return the length, in bytes, of the AMR Narrow-Band frame contained in the given buffer
9828 * @note
9829 * @param pCpAudioFrame (IN) AMRNB frame
9830 * @return M4NO_ERROR: No error
9831 ******************************************************************************
9832 */
M4MCS_intGetFrameSize_AMRNB(M4OSA_MemAddr8 pAudioFrame)9833 static M4OSA_UInt32 M4MCS_intGetFrameSize_AMRNB( M4OSA_MemAddr8 pAudioFrame )
9834 {
9835 M4OSA_UInt32 frameSize = 0;
9836 M4OSA_UInt32 frameType = ( ( *pAudioFrame) &(0xF << 3)) >> 3;
9837
9838 switch( frameType )
9839 {
9840 case 0:
9841 frameSize = 95;
9842 break; /* 4750 bps */
9843
9844 case 1:
9845 frameSize = 103;
9846 break; /* 5150 bps */
9847
9848 case 2:
9849 frameSize = 118;
9850 break; /* 5900 bps */
9851
9852 case 3:
9853 frameSize = 134;
9854 break; /* 6700 bps */
9855
9856 case 4:
9857 frameSize = 148;
9858 break; /* 7400 bps */
9859
9860 case 5:
9861 frameSize = 159;
9862 break; /* 7950 bps */
9863
9864 case 6:
9865 frameSize = 204;
9866 break; /* 10200 bps */
9867
9868 case 7:
9869 frameSize = 244;
9870 break; /* 12000 bps */
9871
9872 case 8:
9873 frameSize = 39;
9874 break; /* SID (Silence) */
9875
9876 case 15:
9877 frameSize = 0;
9878 break; /* No data */
9879
9880 default:
9881 M4OSA_TRACE3_0(
9882 "M4MCS_intGetFrameSize_AMRNB(): Corrupted AMR frame! returning 0.");
9883 return 0;
9884 }
9885
9886 return (1 + (( frameSize + 7) / 8));
9887 }
9888
9889 /**
9890 ******************************************************************************
9891 * M4OSA_UInt32 M4MCS_intGetFrameSize_EVRC(M4OSA_MemAddr8 pAudioFrame)
9892 * @brief Return the length, in bytes, of the EVRC frame contained in the given buffer
9893 * @note
9894 * 0 1 2 3
9895 * +-+-+-+-+
9896 * |fr type| RFC 3558
9897 * +-+-+-+-+
9898 *
9899 * Frame Type: 4 bits
9900 * The frame type indicates the type of the corresponding codec data
9901 * frame in the RTP packet.
9902 *
9903 * For EVRC and SMV codecs, the frame type values and size of the
9904 * associated codec data frame are described in the table below:
9905 *
9906 * Value Rate Total codec data frame size (in octets)
9907 * ---------------------------------------------------------
9908 * 0 Blank 0 (0 bit)
9909 * 1 1/8 2 (16 bits)
9910 * 2 1/4 5 (40 bits; not valid for EVRC)
9911 * 3 1/2 10 (80 bits)
9912 * 4 1 22 (171 bits; 5 padded at end with zeros)
9913 * 5 Erasure 0 (SHOULD NOT be transmitted by sender)
9914 *
9915 * @param pCpAudioFrame (IN) EVRC frame
9916 * @return M4NO_ERROR: No error
9917 ******************************************************************************
9918 */
M4MCS_intGetFrameSize_EVRC(M4OSA_MemAddr8 pAudioFrame)9919 static M4OSA_UInt32 M4MCS_intGetFrameSize_EVRC( M4OSA_MemAddr8 pAudioFrame )
9920 {
9921 M4OSA_UInt32 frameSize = 0;
9922 M4OSA_UInt32 frameType = ( *pAudioFrame) &0x0F;
9923
9924 switch( frameType )
9925 {
9926 case 0:
9927 frameSize = 0;
9928 break; /* blank */
9929
9930 case 1:
9931 frameSize = 16;
9932 break; /* 1/8 */
9933
9934 case 2:
9935 frameSize = 40;
9936 break; /* 1/4 */
9937
9938 case 3:
9939 frameSize = 80;
9940 break; /* 1/2 */
9941
9942 case 4:
9943 frameSize = 171;
9944 break; /* 1 */
9945
9946 case 5:
9947 frameSize = 0;
9948 break; /* erasure */
9949
9950 default:
9951 M4OSA_TRACE3_0(
9952 "M4MCS_intGetFrameSize_EVRC(): Corrupted EVRC frame! returning 0.");
9953 return 0;
9954 }
9955
9956 return (1 + (( frameSize + 7) / 8));
9957 }
9958
9959 /**
9960 ******************************************************************************
9961 * M4OSA_ERR M4MCS_intCheckMaxFileSize(M4MCS_Context pContext)
9962 * @brief Check if max file size is greater enough to encode a file with the
9963 * current selected bitrates and duration.
9964 * @param pContext (IN) MCS context
9965 * @return M4NO_ERROR
9966 * @return M4MCS_ERR_MAXFILESIZE_TOO_SMALL
9967 ******************************************************************************
9968 */
M4MCS_intCheckMaxFileSize(M4MCS_Context pContext)9969 static M4OSA_ERR M4MCS_intCheckMaxFileSize( M4MCS_Context pContext )
9970 {
9971 M4MCS_InternalContext *pC = (M4MCS_InternalContext *)(pContext);
9972
9973 M4OSA_UInt32 duration;
9974 M4OSA_UInt32 audiobitrate;
9975 M4OSA_UInt32 videobitrate;
9976
9977 /* free file size : OK */
9978 if( pC->uiMaxFileSize == 0 )
9979 return M4NO_ERROR;
9980
9981 /* duration */
9982 if( pC->uiEndCutTime == 0 )
9983 {
9984 duration = pC->InputFileProperties.uiClipDuration - pC->uiBeginCutTime;
9985 }
9986 else
9987 {
9988 duration = pC->uiEndCutTime - pC->uiBeginCutTime;
9989 }
9990
9991 /* audio bitrate */
9992 if( pC->noaudio )
9993 {
9994 audiobitrate = 0;
9995 }
9996 else if( pC->AudioEncParams.Format == M4ENCODER_kAudioNULL )
9997 {
9998 audiobitrate = pC->InputFileProperties.uiAudioBitrate;
9999 }
10000 else if( pC->uiAudioBitrate == M4VIDEOEDITING_kUndefinedBitrate )
10001 {
10002 switch( pC->AudioEncParams.Format )
10003 {
10004 case M4ENCODER_kAMRNB:
10005 audiobitrate = M4VIDEOEDITING_k12_2_KBPS;
10006 break;
10007 //EVRC
10008 // case M4ENCODER_kEVRC:
10009 // audiobitrate = M4VIDEOEDITING_k9_2_KBPS;
10010 // break;
10011
10012 default: /* AAC and MP3*/
10013 audiobitrate =
10014 (pC->AudioEncParams.ChannelNum == M4ENCODER_kMono)
10015 ? M4VIDEOEDITING_k16_KBPS : M4VIDEOEDITING_k32_KBPS;
10016 break;
10017 }
10018 }
10019 else
10020 {
10021 audiobitrate = pC->uiAudioBitrate;
10022 }
10023
10024 /* video bitrate */
10025 if( pC->novideo )
10026 {
10027 videobitrate = 0;
10028 }
10029 else if( pC->EncodingVideoFormat == M4ENCODER_kNULL )
10030 {
10031 videobitrate = pC->InputFileProperties.uiVideoBitrate;
10032 }
10033 else if( pC->uiVideoBitrate == M4VIDEOEDITING_kUndefinedBitrate )
10034 {
10035 videobitrate = M4VIDEOEDITING_k16_KBPS;
10036 }
10037 else
10038 {
10039 videobitrate = pC->uiVideoBitrate;
10040 }
10041
10042 /* max file size */
10043 if( (M4OSA_UInt32)pC->uiMaxFileSize
10044 < (M4OSA_UInt32)(M4MCS_MOOV_OVER_FILESIZE_RATIO
10045 * (audiobitrate + videobitrate) * (duration / 8000.0)) )
10046 return M4MCS_ERR_MAXFILESIZE_TOO_SMALL;
10047 else
10048 return M4NO_ERROR;
10049 }
10050
10051 /**
10052 ******************************************************************************
10053 * M4VIDEOEDITING_Bitrate M4MCS_intGetNearestBitrate(M4OSA_UInt32 freebitrate, M4OSA_Int8 mode)
10054 * @brief Returns the closest bitrate value from the enum list of type M4VIDEOEDITING_Bitrate
10055 * @param freebitrate: unsigned int value
10056 * @param mode: -1:previous,0:current,1:next
10057 * @return bitrate value in enum list M4VIDEOEDITING_Bitrate
10058 ******************************************************************************
10059 */
10060 static M4VIDEOEDITING_Bitrate
M4MCS_intGetNearestBitrate(M4OSA_Int32 freebitrate,M4OSA_Int8 mode)10061 M4MCS_intGetNearestBitrate( M4OSA_Int32 freebitrate, M4OSA_Int8 mode )
10062 {
10063 M4OSA_Int32 bitarray [] =
10064 {
10065 0, M4VIDEOEDITING_k16_KBPS, M4VIDEOEDITING_k24_KBPS,
10066 M4VIDEOEDITING_k32_KBPS, M4VIDEOEDITING_k48_KBPS,
10067 M4VIDEOEDITING_k64_KBPS, M4VIDEOEDITING_k96_KBPS,
10068 M4VIDEOEDITING_k128_KBPS, M4VIDEOEDITING_k192_KBPS,
10069 M4VIDEOEDITING_k256_KBPS, M4VIDEOEDITING_k288_KBPS,
10070 M4VIDEOEDITING_k384_KBPS, M4VIDEOEDITING_k512_KBPS,
10071 M4VIDEOEDITING_k800_KBPS, M4VIDEOEDITING_k2_MBPS,
10072 M4VIDEOEDITING_k5_MBPS,
10073 M4VIDEOEDITING_k8_MBPS, /*+ New Encoder bitrates */
10074 M4OSA_INT32_MAX
10075 };
10076
10077 const M4OSA_UInt32 nbbitrates = 14;
10078 M4OSA_UInt32 i;
10079
10080 for ( i = 0; freebitrate >= bitarray[i]; i++ );
10081
10082 switch( mode )
10083 {
10084 case -1: /* previous */
10085 if( i <= 2 )
10086 return 0;
10087 else
10088 return bitarray[i - 2];
10089 break;
10090
10091 case 0: /* current */
10092 if( i <= 1 )
10093 return 0;
10094 else
10095 return bitarray[i - 1];
10096 break;
10097
10098 case 1: /* next */
10099 if( i >= nbbitrates )
10100 return M4OSA_INT32_MAX;
10101 else
10102 return bitarray[i];
10103 break;
10104 }
10105
10106 return 0;
10107 }
10108
10109 /**
10110 ******************************************************************************
10111 * M4OSA_ERR M4MCS_intCleanUp_ReadersDecoders(M4MCS_InternalContext* pC);
10112 * @brief Free all resources allocated by M4MCS_open()
10113 * @param pContext (IN) MCS context
10114 * @return M4NO_ERROR: No error
10115 ******************************************************************************
10116 */
M4MCS_intCleanUp_ReadersDecoders(M4MCS_InternalContext * pC)10117 static M4OSA_ERR M4MCS_intCleanUp_ReadersDecoders( M4MCS_InternalContext *pC )
10118 {
10119 M4OSA_ERR err = M4NO_ERROR;
10120
10121 M4OSA_TRACE2_1("M4MCS_intCleanUp_ReadersDecoders called with pC=0x%x", pC);
10122
10123 /**/
10124 /* ----- Free video decoder stuff, if needed ----- */
10125
10126 if( M4OSA_NULL != pC->pViDecCtxt )
10127 {
10128 err = pC->m_pVideoDecoder->m_pFctDestroy(pC->pViDecCtxt);
10129 pC->pViDecCtxt = M4OSA_NULL;
10130
10131 if( M4NO_ERROR != err )
10132 {
10133 M4OSA_TRACE1_1(
10134 "M4MCS_cleanUp: m_pVideoDecoder->pFctDestroy returns 0x%x",
10135 err);
10136 /**< don't return, we still have stuff to free */
10137 }
10138 }
10139
10140 /* ----- Free the audio decoder stuff ----- */
10141
10142 if( M4OSA_NULL != pC->pAudioDecCtxt )
10143 {
10144 err = pC->m_pAudioDecoder->m_pFctDestroyAudioDec(pC->pAudioDecCtxt);
10145 pC->pAudioDecCtxt = M4OSA_NULL;
10146
10147 if( M4NO_ERROR != err )
10148 {
10149 M4OSA_TRACE1_1(
10150 "M4MCS_cleanUp: m_pAudioDecoder->m_pFctDestroyAudioDec returns 0x%x",
10151 err);
10152 /**< don't return, we still have stuff to free */
10153 }
10154 }
10155
10156 if( M4OSA_NULL != pC->AudioDecBufferOut.m_dataAddress )
10157 {
10158 free(pC->AudioDecBufferOut.m_dataAddress);
10159 pC->AudioDecBufferOut.m_dataAddress = M4OSA_NULL;
10160 }
10161
10162 /* ----- Free reader stuff, if needed ----- */
10163 // We cannot free the reader before decoders because the decoders may read
10164 // from the reader (in another thread) before being stopped.
10165
10166 if( M4OSA_NULL != pC->
10167 pReaderContext ) /**< may be M4OSA_NULL if M4MCS_open was not called */
10168 {
10169 err = pC->m_pReader->m_pFctClose(pC->pReaderContext);
10170
10171 if( M4NO_ERROR != err )
10172 {
10173 M4OSA_TRACE1_1("M4MCS_cleanUp: m_pReader->m_pFctClose returns 0x%x",
10174 err);
10175 /**< don't return, we still have stuff to free */
10176 }
10177
10178 err = pC->m_pReader->m_pFctDestroy(pC->pReaderContext);
10179 pC->pReaderContext = M4OSA_NULL;
10180
10181 if( M4NO_ERROR != err )
10182 {
10183 M4OSA_TRACE1_1(
10184 "M4MCS_cleanUp: m_pReader->m_pFctDestroy returns 0x%x", err);
10185 /**< don't return, we still have stuff to free */
10186 }
10187 }
10188
10189 if( pC->m_pDataAddress1 != M4OSA_NULL )
10190 {
10191 free(pC->m_pDataAddress1);
10192 pC->m_pDataAddress1 = M4OSA_NULL;
10193 }
10194
10195 if( pC->m_pDataAddress2 != M4OSA_NULL )
10196 {
10197 free(pC->m_pDataAddress2);
10198 pC->m_pDataAddress2 = M4OSA_NULL;
10199 }
10200 /*Bug fix 11/12/2008 (to obtain more precise video end cut)*/
10201 if( pC->m_pDataVideoAddress1 != M4OSA_NULL )
10202 {
10203 free(pC->m_pDataVideoAddress1);
10204 pC->m_pDataVideoAddress1 = M4OSA_NULL;
10205 }
10206
10207 if( pC->m_pDataVideoAddress2 != M4OSA_NULL )
10208 {
10209 free(pC->m_pDataVideoAddress2);
10210 pC->m_pDataVideoAddress2 = M4OSA_NULL;
10211 }
10212
10213 return M4NO_ERROR;
10214 }
10215
10216
10217 /**
10218
10219 ******************************************************************************
10220 * M4OSA_ERR M4MCS_open_normalMode(M4MCS_Context pContext, M4OSA_Void* pFileIn,
10221 * M4OSA_Void* pFileOut, M4OSA_Void* pTempFile);
10222 * @brief Set the MCS input and output files. It is the same as M4MCS_open without
10223 * M4MCS_WITH_FAST_OPEN flag
10224 It is used in VideoArtist
10225 * @note It opens the input file, but the output file is not created yet.
10226 * @param pContext (IN) MCS context
10227 * @param pFileIn (IN) Input file to transcode (The type of this parameter
10228 * (URL, pipe...) depends on the OSAL implementation).
10229 * @param mediaType (IN) Container type (.3gp,.amr, ...) of input file.
10230 * @param pFileOut (IN) Output file to create (The type of this parameter
10231 * (URL, pipe...) depends on the OSAL implementation).
10232 * @param pTempFile (IN) Temporary file for the constant memory writer to store
10233 * metadata ("moov.bin").
10234 * @return M4NO_ERROR: No error
10235 * @return M4ERR_PARAMETER: At least one parameter is M4OSA_NULL (debug only)
10236 * @return M4ERR_STATE: MCS is not in an appropriate state for this function to be called
10237 * @return M4ERR_ALLOC: There is no more available memory
10238 * @return M4ERR_FILE_NOT_FOUND: The input file has not been found
10239 * @return M4MCS_ERR_INVALID_INPUT_FILE: The input file is not a valid file, or is corrupted
10240 * @return M4MCS_ERR_INPUT_FILE_CONTAINS_NO_SUPPORTED_STREAM: The input file contains no
10241 * supported audio or video stream
10242 ******************************************************************************
10243 */
M4MCS_open_normalMode(M4MCS_Context pContext,M4OSA_Void * pFileIn,M4VIDEOEDITING_FileType InputFileType,M4OSA_Void * pFileOut,M4OSA_Void * pTempFile)10244 M4OSA_ERR M4MCS_open_normalMode(M4MCS_Context pContext, M4OSA_Void* pFileIn,
10245 M4VIDEOEDITING_FileType InputFileType,
10246 M4OSA_Void* pFileOut, M4OSA_Void* pTempFile)
10247 {
10248 M4MCS_InternalContext *pC = (M4MCS_InternalContext*)(pContext);
10249 M4OSA_ERR err;
10250
10251 M4READER_MediaFamily mediaFamily;
10252 M4_StreamHandler* pStreamHandler;
10253
10254 M4OSA_TRACE2_3("M4MCS_open_normalMode called with pContext=0x%x, pFileIn=0x%x,\
10255 pFileOut=0x%x", pContext, pFileIn, pFileOut);
10256
10257 /**
10258 * Check input parameters */
10259 M4OSA_DEBUG_IF2((M4OSA_NULL == pContext), M4ERR_PARAMETER,
10260 "M4MCS_open_normalMode: pContext is M4OSA_NULL");
10261 M4OSA_DEBUG_IF2((M4OSA_NULL == pFileIn) , M4ERR_PARAMETER,
10262 "M4MCS_open_normalMode: pFileIn is M4OSA_NULL");
10263
10264 if ((InputFileType == M4VIDEOEDITING_kFileType_JPG)
10265 ||(InputFileType == M4VIDEOEDITING_kFileType_PNG)
10266 ||(InputFileType == M4VIDEOEDITING_kFileType_GIF)
10267 ||(InputFileType == M4VIDEOEDITING_kFileType_BMP))
10268 {
10269 M4OSA_TRACE1_0("M4MCS_open_normalMode: Still picture is not\
10270 supported with this function");
10271 return M4MCS_ERR_INPUT_FILE_CONTAINS_NO_SUPPORTED_STREAM;
10272 }
10273
10274 /**
10275 * Check state automaton */
10276 if (M4MCS_kState_CREATED != pC->State)
10277 {
10278 M4OSA_TRACE1_1("M4MCS_open_normalMode(): Wrong State (%d), returning M4ERR_STATE",
10279 pC->State);
10280 return M4ERR_STATE;
10281 }
10282
10283 /* Copy function input parameters into our context */
10284 pC->pInputFile = pFileIn;
10285 pC->InputFileType = InputFileType;
10286 pC->pOutputFile = pFileOut;
10287 pC->pTemporaryFile = pTempFile;
10288
10289 /***********************************/
10290 /* Open input file with the reader */
10291 /***********************************/
10292
10293 err = M4MCS_setCurrentReader(pContext, pC->InputFileType);
10294 M4ERR_CHECK_RETURN(err);
10295
10296 /**
10297 * Reset reader related variables */
10298 pC->VideoState = M4MCS_kStreamState_NOSTREAM;
10299 pC->AudioState = M4MCS_kStreamState_NOSTREAM;
10300 pC->pReaderVideoStream = M4OSA_NULL;
10301 pC->pReaderAudioStream = M4OSA_NULL;
10302
10303 /*******************************************************/
10304 /* Initializes the reader shell and open the data file */
10305 /*******************************************************/
10306 err = pC->m_pReader->m_pFctCreate(&pC->pReaderContext);
10307 if (M4NO_ERROR != err)
10308 {
10309 M4OSA_TRACE1_1("M4MCS_open_normalMode(): m_pReader->m_pFctCreate returns 0x%x", err);
10310 return err;
10311 }
10312
10313 /**
10314 * Link the reader interface to the reader context */
10315 pC->m_pReaderDataIt->m_readerContext = pC->pReaderContext;
10316
10317 /**
10318 * Set the reader shell file access functions */
10319 err = pC->m_pReader->m_pFctSetOption(pC->pReaderContext,
10320 M4READER_kOptionID_SetOsaFileReaderFctsPtr,
10321 (M4OSA_DataOption)pC->pOsaFileReadPtr);
10322 if (M4NO_ERROR != err)
10323 {
10324 M4OSA_TRACE1_1("M4MCS_open_normalMode(): m_pReader->m_pFctSetOption returns 0x%x", err);
10325 return err;
10326 }
10327
10328 /**
10329 * Open the input file */
10330 err = pC->m_pReader->m_pFctOpen(pC->pReaderContext, pC->pInputFile);
10331 if (M4NO_ERROR != err)
10332 {
10333 M4OSA_UInt32 uiDummy, uiCoreId;
10334 M4OSA_TRACE1_1("M4MCS_open_normalMode(): m_pReader->m_pFctOpen returns 0x%x", err);
10335
10336 if (err == ((M4OSA_UInt32)M4ERR_UNSUPPORTED_MEDIA_TYPE)) {
10337 M4OSA_TRACE1_0("M4MCS_open_normalMode(): returning M4MCS_ERR_FILE_DRM_PROTECTED");
10338 return M4MCS_ERR_FILE_DRM_PROTECTED;
10339 } else {
10340 /**
10341 * If the error is from the core reader, we change it to a public VXS error */
10342 M4OSA_ERR_SPLIT(err, uiDummy, uiCoreId, uiDummy);
10343 if (M4MP4_READER == uiCoreId)
10344 {
10345 M4OSA_TRACE1_0("M4MCS_open_normalMode(): returning M4MCS_ERR_INVALID_INPUT_FILE");
10346 return M4MCS_ERR_INVALID_INPUT_FILE;
10347 }
10348 }
10349 return err;
10350 }
10351
10352 /**
10353 * Get the streams from the input file */
10354 while (M4NO_ERROR == err)
10355 {
10356 err = pC->m_pReader->m_pFctGetNextStream(pC->pReaderContext, &mediaFamily,
10357 &pStreamHandler);
10358
10359 /**
10360 * In case we found a BIFS stream or something else...*/
10361 if((err == ((M4OSA_UInt32)M4ERR_READER_UNKNOWN_STREAM_TYPE))
10362 || (err == ((M4OSA_UInt32)M4WAR_TOO_MUCH_STREAMS)))
10363 {
10364 err = M4NO_ERROR;
10365 continue;
10366 }
10367
10368 if (M4NO_ERROR == err) /**< One stream found */
10369 {
10370 /**
10371 * Found the first video stream */
10372 if ((M4READER_kMediaFamilyVideo == mediaFamily) \
10373 && (M4OSA_NULL == pC->pReaderVideoStream))
10374 {
10375 if ((M4DA_StreamTypeVideoH263==pStreamHandler->m_streamType) ||
10376 (M4DA_StreamTypeVideoMpeg4==pStreamHandler->m_streamType)
10377 #ifdef M4VSS_SUPPORT_VIDEO_AVC
10378 ||(M4DA_StreamTypeVideoMpeg4Avc==pStreamHandler->m_streamType))
10379 #else
10380 ||((M4DA_StreamTypeVideoMpeg4Avc==pStreamHandler->m_streamType)
10381 &&(pC->m_pVideoDecoderItTable[M4DECODER_kVideoTypeAVC] != M4OSA_NULL)))
10382 #endif
10383 {
10384 M4OSA_TRACE3_0("M4MCS_open_normalMode():\
10385 Found a H263 or MPEG-4 video stream in input 3gpp clip");
10386
10387 /**
10388 * Keep pointer to the video stream */
10389 pC->pReaderVideoStream = (M4_VideoStreamHandler*)pStreamHandler;
10390 pC->bUnsupportedVideoFound = M4OSA_FALSE;
10391 pStreamHandler->m_bStreamIsOK = M4OSA_TRUE;
10392
10393 /**
10394 * Init our video stream state variable */
10395 pC->VideoState = M4MCS_kStreamState_STARTED;
10396
10397 /**
10398 * Reset the stream reader */
10399 err = pC->m_pReader->m_pFctReset(pC->pReaderContext,
10400 (M4_StreamHandler*)pC->pReaderVideoStream);
10401 if (M4NO_ERROR != err)
10402 {
10403 M4OSA_TRACE1_1("M4MCS_open_normalMode():\
10404 m_pReader->m_pFctReset(video) returns 0x%x", err);
10405 return err;
10406 }
10407
10408 /**
10409 * Initializes an access Unit */
10410 err = pC->m_pReader->m_pFctFillAuStruct(pC->pReaderContext, pStreamHandler,
10411 &pC->ReaderVideoAU);
10412 if (M4NO_ERROR != err)
10413 {
10414 M4OSA_TRACE1_1("M4MCS_open_normalMode():\
10415 m_pReader->m_pFctFillAuStruct(video) returns 0x%x", err);
10416 return err;
10417 }
10418 }
10419 else /**< Not H263 or MPEG-4 (H264, etc.) */
10420 {
10421 M4OSA_TRACE1_1("M4MCS_open_normalMode():\
10422 Found an unsupported video stream (0x%x) in input 3gpp clip",
10423 pStreamHandler->m_streamType);
10424
10425 pC->bUnsupportedVideoFound = M4OSA_TRUE;
10426 pStreamHandler->m_bStreamIsOK = M4OSA_FALSE;
10427 }
10428 }
10429 /**
10430 * Found the first audio stream */
10431 else if ((M4READER_kMediaFamilyAudio == mediaFamily)
10432 && (M4OSA_NULL == pC->pReaderAudioStream))
10433 {
10434 if ((M4DA_StreamTypeAudioAmrNarrowBand==pStreamHandler->m_streamType) ||
10435 (M4DA_StreamTypeAudioAac==pStreamHandler->m_streamType) ||
10436 (M4DA_StreamTypeAudioMp3==pStreamHandler->m_streamType) ||
10437 (M4DA_StreamTypeAudioEvrc==pStreamHandler->m_streamType) )
10438 {
10439 M4OSA_TRACE3_0("M4MCS_open_normalMode(): Found an AMR-NB, AAC \
10440 or MP3 audio stream in input clip");
10441
10442 /**
10443 * Keep pointer to the audio stream */
10444 pC->pReaderAudioStream = (M4_AudioStreamHandler*)pStreamHandler;
10445 pStreamHandler->m_bStreamIsOK = M4OSA_TRUE;
10446 pC->bUnsupportedAudioFound = M4OSA_FALSE;
10447
10448 /**
10449 * Init our audio stream state variable */
10450 pC->AudioState = M4MCS_kStreamState_STARTED;
10451
10452 /**
10453 * Reset the stream reader */
10454 err = pC->m_pReader->m_pFctReset(pC->pReaderContext,
10455 (M4_StreamHandler*)pC->pReaderAudioStream);
10456 if (M4NO_ERROR != err)
10457 {
10458 M4OSA_TRACE1_1("M4MCS_open_normalMode():\
10459 m_pReader->m_pFctReset(audio) returns 0x%x", err);
10460 return err;
10461 }
10462
10463 /**
10464 * Initializes an access Unit */
10465 err = pC->m_pReader->m_pFctFillAuStruct(pC->pReaderContext, pStreamHandler,
10466 &pC->ReaderAudioAU);
10467 if (M4NO_ERROR != err)
10468 {
10469 M4OSA_TRACE1_1("M4MCS_open_normalMode(): \
10470 m_pReader->m_pFctFillAuStruct(audio) returns 0x%x", err);
10471 return err;
10472 }
10473
10474 /**
10475 * Output max AU size is equal to input max AU size (this value
10476 * will be changed if there is audio transcoding) */
10477 pC->uiAudioMaxAuSize = pStreamHandler->m_maxAUSize;
10478
10479 }
10480 else
10481 {
10482 /**< Not AMR-NB, AAC, MP3 nor EVRC (AMR-WB, WAV...) */
10483 M4OSA_TRACE1_1("M4MCS_open_normalMode(): Found an unsupported audio stream\
10484 (0x%x) in input 3gpp clip", pStreamHandler->m_streamType);
10485
10486 pC->bUnsupportedAudioFound = M4OSA_TRUE;
10487 pStreamHandler->m_bStreamIsOK = M4OSA_FALSE;
10488 }
10489 }
10490 }
10491 } /**< end of while (M4NO_ERROR == err) */
10492
10493 /**
10494 * Check we found at least one supported stream */
10495 if((M4OSA_NULL == pC->pReaderVideoStream) && (M4OSA_NULL == pC->pReaderAudioStream))
10496 {
10497 M4OSA_TRACE1_0("M4MCS_open_normalMode(): returning \
10498 M4MCS_ERR_INPUT_FILE_CONTAINS_NO_SUPPORTED_STREAM");
10499 return M4MCS_ERR_INPUT_FILE_CONTAINS_NO_SUPPORTED_STREAM;
10500 }
10501
10502 #ifndef M4VSS_ENABLE_EXTERNAL_DECODERS
10503 if(pC->VideoState == M4MCS_kStreamState_STARTED)
10504 {
10505 err = M4MCS_setCurrentVideoDecoder(pContext,
10506 pC->pReaderVideoStream->m_basicProperties.m_streamType);
10507 M4ERR_CHECK_RETURN(err);
10508 }
10509 #endif
10510
10511 if(pC->AudioState == M4MCS_kStreamState_STARTED)
10512 {
10513 //EVRC
10514 if(M4DA_StreamTypeAudioEvrc != pStreamHandler->m_streamType)
10515 /* decoder not supported yet, but allow to do null encoding */
10516 {
10517 err = M4MCS_setCurrentAudioDecoder(pContext,
10518 pC->pReaderAudioStream->m_basicProperties.m_streamType);
10519 M4ERR_CHECK_RETURN(err);
10520 }
10521 }
10522
10523 /**
10524 * Get the audio and video stream properties */
10525 err = M4MCS_intGetInputClipProperties(pC);
10526 if (M4NO_ERROR != err)
10527 {
10528 M4OSA_TRACE1_1("M4MCS_open_normalMode():\
10529 M4MCS_intGetInputClipProperties returns 0x%x", err);
10530 return err;
10531 }
10532
10533 /**
10534 * Set the begin cut decoding increment according to the input frame rate */
10535 if (0. != pC->InputFileProperties.fAverageFrameRate) /**< sanity check */
10536 {
10537 pC->iVideoBeginDecIncr = (M4OSA_Int32)(3000. \
10538 / pC->InputFileProperties.fAverageFrameRate); /**< about 3 frames */
10539 }
10540 else
10541 {
10542 pC->iVideoBeginDecIncr = 200; /**< default value: 200 milliseconds (3 frames @ 15fps)*/
10543 }
10544
10545 /**
10546 * Update state automaton */
10547 pC->State = M4MCS_kState_OPENED;
10548
10549 /**
10550 * Return with no error */
10551 M4OSA_TRACE3_0("M4MCS_open_normalMode(): returning M4NO_ERROR");
10552 return M4NO_ERROR;
10553 }
10554
M4MCS_intCheckAndGetCodecProperties(M4MCS_InternalContext * pC)10555 M4OSA_ERR M4MCS_intCheckAndGetCodecProperties(
10556 M4MCS_InternalContext *pC) {
10557
10558 M4OSA_ERR err = M4NO_ERROR;
10559 M4AD_Buffer outputBuffer;
10560 uint32_t optionValue =0;
10561
10562 M4OSA_TRACE3_0("M4MCS_intCheckAndGetCodecProperties :start");
10563
10564 // Decode first audio frame from clip to get properties from codec
10565
10566 if (M4DA_StreamTypeAudioAac ==
10567 pC->pReaderAudioStream->m_basicProperties.m_streamType) {
10568
10569 err = pC->m_pAudioDecoder->m_pFctCreateAudioDec(
10570 &pC->pAudioDecCtxt,
10571 pC->pReaderAudioStream, &(pC->AacProperties));
10572 } else {
10573 err = pC->m_pAudioDecoder->m_pFctCreateAudioDec(
10574 &pC->pAudioDecCtxt,
10575 pC->pReaderAudioStream,
10576 pC->m_pCurrentAudioDecoderUserData);
10577 }
10578 if (M4NO_ERROR != err) {
10579
10580 M4OSA_TRACE1_1(
10581 "M4MCS_intCheckAndGetCodecProperties: m_pFctCreateAudioDec \
10582 returns 0x%x", err);
10583 return err;
10584 }
10585
10586 pC->m_pAudioDecoder->m_pFctSetOptionAudioDec(pC->pAudioDecCtxt,
10587 M4AD_kOptionID_3gpReaderInterface, (M4OSA_DataOption) pC->m_pReaderDataIt);
10588
10589 pC->m_pAudioDecoder->m_pFctSetOptionAudioDec(pC->pAudioDecCtxt,
10590 M4AD_kOptionID_AudioAU, (M4OSA_DataOption) &pC->ReaderAudioAU);
10591
10592 if( pC->m_pAudioDecoder->m_pFctStartAudioDec != M4OSA_NULL ) {
10593
10594 err = pC->m_pAudioDecoder->m_pFctStartAudioDec(pC->pAudioDecCtxt);
10595 if( M4NO_ERROR != err ) {
10596
10597 M4OSA_TRACE1_1(
10598 "M4MCS_intCheckAndGetCodecProperties: m_pFctStartAudioDec \
10599 returns 0x%x", err);
10600 return err;
10601 }
10602 }
10603
10604 /**
10605 * Allocate output buffer for the audio decoder */
10606 outputBuffer.m_bufferSize =
10607 pC->pReaderAudioStream->m_byteFrameLength
10608 * pC->pReaderAudioStream->m_byteSampleSize
10609 * pC->pReaderAudioStream->m_nbChannels;
10610
10611 if( outputBuffer.m_bufferSize > 0 ) {
10612
10613 outputBuffer.m_dataAddress =
10614 (M4OSA_MemAddr8)M4OSA_32bitAlignedMalloc(outputBuffer.m_bufferSize \
10615 *sizeof(short), M4MCS, (M4OSA_Char *)"outputBuffer.m_bufferSize");
10616
10617 if( M4OSA_NULL == outputBuffer.m_dataAddress ) {
10618
10619 M4OSA_TRACE1_0(
10620 "M4MCS_intCheckAndGetCodecProperties():\
10621 unable to allocate outputBuffer.m_dataAddress, returning M4ERR_ALLOC");
10622 return M4ERR_ALLOC;
10623 }
10624 }
10625
10626 err = pC->m_pAudioDecoder->m_pFctStepAudioDec(pC->pAudioDecCtxt,
10627 M4OSA_NULL, &outputBuffer, M4OSA_FALSE);
10628
10629 if ( err == M4WAR_INFO_FORMAT_CHANGE ) {
10630
10631 // Get the properties from codec node
10632 pC->m_pAudioDecoder->m_pFctGetOptionAudioDec(pC->pAudioDecCtxt,
10633 M4AD_kOptionID_AudioNbChannels, (M4OSA_DataOption) &optionValue);
10634
10635 // Reset Reader structure value also
10636 pC->pReaderAudioStream->m_nbChannels = optionValue;
10637
10638 pC->m_pAudioDecoder->m_pFctGetOptionAudioDec(pC->pAudioDecCtxt,
10639 M4AD_kOptionID_AudioSampFrequency, (M4OSA_DataOption) &optionValue);
10640
10641 // Reset Reader structure value also
10642 pC->pReaderAudioStream->m_samplingFrequency = optionValue;
10643
10644 if (M4DA_StreamTypeAudioAac ==
10645 pC->pReaderAudioStream->m_basicProperties.m_streamType) {
10646
10647 pC->AacProperties.aNumChan =
10648 pC->pReaderAudioStream->m_nbChannels;
10649 pC->AacProperties.aSampFreq =
10650 pC->pReaderAudioStream->m_samplingFrequency;
10651
10652 }
10653
10654 } else if( err != M4NO_ERROR) {
10655 M4OSA_TRACE1_1("M4MCS_intCheckAndGetCodecProperties:\
10656 m_pFctStepAudioDec returns err = 0x%x", err);
10657 }
10658
10659 free(outputBuffer.m_dataAddress);
10660
10661 // Reset the stream reader
10662 err = pC->m_pReader->m_pFctReset(pC->pReaderContext,
10663 (M4_StreamHandler *)pC->pReaderAudioStream);
10664
10665 if (M4NO_ERROR != err) {
10666 M4OSA_TRACE1_1("M4MCS_intCheckAndGetCodecProperties\
10667 Error in reseting reader: 0x%x", err);
10668 }
10669
10670 return err;
10671
10672 }
10673
M4MCS_intLimitBitratePerCodecProfileLevel(M4ENCODER_AdvancedParams * EncParams)10674 M4OSA_ERR M4MCS_intLimitBitratePerCodecProfileLevel(
10675 M4ENCODER_AdvancedParams* EncParams) {
10676
10677 M4OSA_ERR err = M4NO_ERROR;
10678
10679 switch (EncParams->Format) {
10680 case M4ENCODER_kH263:
10681 EncParams->Bitrate = M4MCS_intLimitBitrateForH263Enc(
10682 EncParams->videoProfile,
10683 EncParams->videoLevel, EncParams->Bitrate);
10684 break;
10685
10686 case M4ENCODER_kMPEG4:
10687 EncParams->Bitrate = M4MCS_intLimitBitrateForMpeg4Enc(
10688 EncParams->videoProfile,
10689 EncParams->videoLevel, EncParams->Bitrate);
10690 break;
10691
10692 case M4ENCODER_kH264:
10693 EncParams->Bitrate = M4MCS_intLimitBitrateForH264Enc(
10694 EncParams->videoProfile,
10695 EncParams->videoLevel, EncParams->Bitrate);
10696 break;
10697
10698 default:
10699 M4OSA_TRACE1_1("M4MCS_intLimitBitratePerCodecProfileLevel: \
10700 Wrong enc format %d", EncParams->Format);
10701 err = M4ERR_PARAMETER;
10702 break;
10703 }
10704
10705 return err;
10706
10707 }
10708
M4MCS_intLimitBitrateForH264Enc(M4OSA_Int32 profile,M4OSA_Int32 level,M4OSA_Int32 bitrate)10709 M4OSA_Int32 M4MCS_intLimitBitrateForH264Enc(M4OSA_Int32 profile,
10710 M4OSA_Int32 level, M4OSA_Int32 bitrate) {
10711
10712 M4OSA_Int32 vidBitrate = 0;
10713
10714 switch (profile) {
10715 case OMX_VIDEO_AVCProfileBaseline:
10716 case OMX_VIDEO_AVCProfileMain:
10717
10718 switch (level) {
10719
10720 case OMX_VIDEO_AVCLevel1:
10721 vidBitrate = (bitrate > 64000) ? 64000 : bitrate;
10722 break;
10723
10724 case OMX_VIDEO_AVCLevel1b:
10725 vidBitrate = (bitrate > 128000) ? 128000 : bitrate;
10726 break;
10727
10728 case OMX_VIDEO_AVCLevel11:
10729 vidBitrate = (bitrate > 192000) ? 192000 : bitrate;
10730 break;
10731
10732 case OMX_VIDEO_AVCLevel12:
10733 vidBitrate = (bitrate > 384000) ? 384000 : bitrate;
10734 break;
10735
10736 case OMX_VIDEO_AVCLevel13:
10737 vidBitrate = (bitrate > 768000) ? 768000 : bitrate;
10738 break;
10739
10740 case OMX_VIDEO_AVCLevel2:
10741 vidBitrate = (bitrate > 2000000) ? 2000000 : bitrate;
10742 break;
10743
10744 case OMX_VIDEO_AVCLevel21:
10745 vidBitrate = (bitrate > 4000000) ? 4000000 : bitrate;
10746 break;
10747
10748 case OMX_VIDEO_AVCLevel22:
10749 vidBitrate = (bitrate > 4000000) ? 4000000 : bitrate;
10750 break;
10751
10752 case OMX_VIDEO_AVCLevel3:
10753 vidBitrate = (bitrate > 10000000) ? 10000000 : bitrate;
10754 break;
10755
10756 case OMX_VIDEO_AVCLevel31:
10757 vidBitrate = (bitrate > 14000000) ? 14000000 : bitrate;
10758 break;
10759
10760 case OMX_VIDEO_AVCLevel32:
10761 vidBitrate = (bitrate > 20000000) ? 20000000 : bitrate;
10762 break;
10763
10764 case OMX_VIDEO_AVCLevel4:
10765 vidBitrate = (bitrate > 20000000) ? 20000000 : bitrate;
10766 break;
10767
10768 case OMX_VIDEO_AVCLevel41:
10769 vidBitrate = (bitrate > 50000000) ? 50000000 : bitrate;
10770 break;
10771
10772 case OMX_VIDEO_AVCLevel42:
10773 vidBitrate = (bitrate > 50000000) ? 50000000 : bitrate;
10774 break;
10775
10776 case OMX_VIDEO_AVCLevel5:
10777 vidBitrate = (bitrate > 135000000) ? 135000000 : bitrate;
10778 break;
10779
10780 case OMX_VIDEO_AVCLevel51:
10781 vidBitrate = (bitrate > 240000000) ? 240000000 : bitrate;
10782 break;
10783
10784 default:
10785 vidBitrate = bitrate;
10786 break;
10787 }
10788 break;
10789
10790 case OMX_VIDEO_AVCProfileHigh:
10791 switch (level) {
10792 case OMX_VIDEO_AVCLevel1:
10793 vidBitrate = (bitrate > 80000) ? 80000 : bitrate;
10794 break;
10795
10796 case OMX_VIDEO_AVCLevel1b:
10797 vidBitrate = (bitrate > 160000) ? 160000 : bitrate;
10798 break;
10799
10800 case OMX_VIDEO_AVCLevel11:
10801 vidBitrate = (bitrate > 240000) ? 240000 : bitrate;
10802 break;
10803
10804 case OMX_VIDEO_AVCLevel12:
10805 vidBitrate = (bitrate > 480000) ? 480000 : bitrate;
10806 break;
10807
10808 case OMX_VIDEO_AVCLevel13:
10809 vidBitrate = (bitrate > 960000) ? 960000 : bitrate;
10810 break;
10811
10812 case OMX_VIDEO_AVCLevel2:
10813 vidBitrate = (bitrate > 2500000) ? 2500000 : bitrate;
10814 break;
10815
10816 case OMX_VIDEO_AVCLevel21:
10817 vidBitrate = (bitrate > 5000000) ? 5000000 : bitrate;
10818 break;
10819
10820 case OMX_VIDEO_AVCLevel22:
10821 vidBitrate = (bitrate > 5000000) ? 5000000 : bitrate;
10822 break;
10823
10824 case OMX_VIDEO_AVCLevel3:
10825 vidBitrate = (bitrate > 12500000) ? 12500000 : bitrate;
10826 break;
10827
10828 case OMX_VIDEO_AVCLevel31:
10829 vidBitrate = (bitrate > 17500000) ? 17500000 : bitrate;
10830 break;
10831
10832 case OMX_VIDEO_AVCLevel32:
10833 vidBitrate = (bitrate > 25000000) ? 25000000 : bitrate;
10834 break;
10835
10836 case OMX_VIDEO_AVCLevel4:
10837 vidBitrate = (bitrate > 25000000) ? 25000000 : bitrate;
10838 break;
10839
10840 case OMX_VIDEO_AVCLevel41:
10841 vidBitrate = (bitrate > 62500000) ? 62500000 : bitrate;
10842 break;
10843
10844 case OMX_VIDEO_AVCLevel42:
10845 vidBitrate = (bitrate > 62500000) ? 62500000 : bitrate;
10846 break;
10847
10848 case OMX_VIDEO_AVCLevel5:
10849 vidBitrate = (bitrate > 168750000) ? 168750000 : bitrate;
10850 break;
10851
10852 case OMX_VIDEO_AVCLevel51:
10853 vidBitrate = (bitrate > 300000000) ? 300000000 : bitrate;
10854 break;
10855
10856 default:
10857 vidBitrate = bitrate;
10858 break;
10859 }
10860 break;
10861
10862 default:
10863 // We do not handle any other AVC profile for now.
10864 // Return input bitrate
10865 vidBitrate = bitrate;
10866 break;
10867 }
10868
10869 return vidBitrate;
10870 }
10871
M4MCS_intLimitBitrateForMpeg4Enc(M4OSA_Int32 profile,M4OSA_Int32 level,M4OSA_Int32 bitrate)10872 M4OSA_Int32 M4MCS_intLimitBitrateForMpeg4Enc(M4OSA_Int32 profile,
10873 M4OSA_Int32 level, M4OSA_Int32 bitrate) {
10874
10875 M4OSA_Int32 vidBitrate = 0;
10876
10877 switch (profile) {
10878 case OMX_VIDEO_MPEG4ProfileSimple:
10879 switch (level) {
10880
10881 case OMX_VIDEO_MPEG4Level0:
10882 vidBitrate = (bitrate > 64000) ? 64000 : bitrate;
10883 break;
10884
10885 case OMX_VIDEO_MPEG4Level0b:
10886 vidBitrate = (bitrate > 128000) ? 128000 : bitrate;
10887 break;
10888
10889 case OMX_VIDEO_MPEG4Level1:
10890 vidBitrate = (bitrate > 64000) ? 64000 : bitrate;
10891 break;
10892
10893 case OMX_VIDEO_MPEG4Level2:
10894 vidBitrate = (bitrate > 128000) ? 128000 : bitrate;
10895 break;
10896
10897 case OMX_VIDEO_MPEG4Level3:
10898 vidBitrate = (bitrate > 384000) ? 384000 : bitrate;
10899 break;
10900
10901 default:
10902 vidBitrate = bitrate;
10903 break;
10904 }
10905 break;
10906
10907 default:
10908 // We do not handle any other MPEG4 profile for now.
10909 // Return input bitrate
10910 vidBitrate = bitrate;
10911 break;
10912 }
10913
10914 return vidBitrate;
10915 }
10916
M4MCS_intLimitBitrateForH263Enc(M4OSA_Int32 profile,M4OSA_Int32 level,M4OSA_Int32 bitrate)10917 M4OSA_Int32 M4MCS_intLimitBitrateForH263Enc(M4OSA_Int32 profile,
10918 M4OSA_Int32 level, M4OSA_Int32 bitrate) {
10919
10920 M4OSA_Int32 vidBitrate = 0;
10921
10922 switch (profile) {
10923 case OMX_VIDEO_H263ProfileBaseline:
10924 switch (level) {
10925
10926 case OMX_VIDEO_H263Level10:
10927 vidBitrate = (bitrate > 64000) ? 64000 : bitrate;
10928 break;
10929
10930 case OMX_VIDEO_H263Level20:
10931 vidBitrate = (bitrate > 128000) ? 128000 : bitrate;
10932 break;
10933
10934 case OMX_VIDEO_H263Level30:
10935 vidBitrate = (bitrate > 384000) ? 384000 : bitrate;
10936 break;
10937
10938 default:
10939 vidBitrate = bitrate;
10940 break;
10941 }
10942 break;
10943
10944 default:
10945 // We do not handle any other H263 profile for now.
10946 // Return input bitrate
10947 vidBitrate = bitrate;
10948 break;
10949 }
10950
10951 return vidBitrate;
10952 }
10953