1 /* |
|
2 * Copyright (c) 2010 Ixonos Plc. |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of the "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - Initial contribution |
|
11 * |
|
12 * Contributors: |
|
13 * Ixonos Plc |
|
14 * |
|
15 * Description: |
|
16 * Video decoder control interface. |
|
17 * |
|
18 */ |
|
19 |
|
20 |
|
21 |
|
22 /* |
|
23 * Includes |
|
24 */ |
|
25 |
|
26 /* Include the definition header for the active build target */ |
|
27 #include "h263dConfig.h" |
|
28 /* Include the header for this file */ |
|
29 #include "h263dntc.h" |
|
30 /* All other inclusions */ |
|
31 #include "biblin.h" |
|
32 #include "h263dapi.h" |
|
33 #include "vde.h" |
|
34 #include "vdemain.h" |
|
35 #include "vdeti.h" |
|
36 #include "biblin.h" |
|
37 /* MVE */ |
|
38 //#include "InnerTranscoder.h" |
|
39 #include "core.h" |
|
40 #include "MPEG4Transcoder.h" |
|
41 |
|
42 /* |
|
43 * Constants |
|
44 */ |
|
45 const TUint KH263StartCodeLength = 3; // H.263 picture start code length |
|
46 const TUint KMPEG4StartCodeLength = 4; // MPEG4 picture start code length |
|
47 |
|
48 /* |
|
49 * Global functions |
|
50 */ |
|
51 |
|
52 /* {{-output"h263dClose.txt"}} */ |
|
53 /* |
|
54 * h263dClose |
|
55 * |
|
56 * |
|
57 * Parameters: |
|
58 * hInstance instance handle |
|
59 * |
|
60 * Function: |
|
61 * This function closes an H.263 decoder instance. |
|
62 * |
|
63 * Returns: |
|
64 * Nothing |
|
65 */ |
|
66 |
|
67 void H263D_CC h263dClose(h263dHInstance_t hInstance) |
|
68 /* {{-output"h263dClose.txt"}} */ |
|
69 { |
|
70 if (hInstance) |
|
71 vdeShutDown(hInstance); |
|
72 } |
|
73 |
|
74 |
|
75 /* {{-output"h263dDecodeFrame.txt"}} */ |
|
76 /* |
|
77 * h263dDecodeFrameL |
|
78 * |
|
79 * |
|
80 * Parameters: |
|
81 * hInstance instance data |
|
82 * pStreamBuffer pointer to input data (>= 1 video frames) |
|
83 * streamBufferSize size of pStreamBuffer |
|
84 * fFirstFrame pointer to flag telling if the very first |
|
85 * frame is being decoded |
|
86 * frameSize If non-NULL, frameSize is used to return |
|
87 * the number of bytes that were decoded |
|
88 * to produce the reconstructed output frame. |
|
89 * |
|
90 * Function: |
|
91 * This function decodes the bitstream until it gets at least one decoded |
|
92 * frame. It also shows the resulting frames. |
|
93 * In addition, the function handles the parameter updating synchronization. |
|
94 * |
|
95 * Returns: |
|
96 * H263D_OK if the function was successful |
|
97 * H263D_OK_EOS if the end of stream has been reached |
|
98 * H263D_ERROR if a fatal error, from which the decoder |
|
99 * cannot be restored, has occured |
|
100 * H263D_ERROR_HALTED the instance is halted, it should be closed |
|
101 */ |
|
102 |
|
103 int H263D_CC h263dDecodeFrameL(h263dHInstance_t hInstance, |
|
104 void *pStreamBuffer, |
|
105 void *pOutStreamBuffer, |
|
106 unsigned streamBufferSize, |
|
107 u_char *fFirstFrame, |
|
108 TInt *frameSize, |
|
109 TInt *outframeSize, |
|
110 vdeDecodeParamters_t *aDecoderInfo |
|
111 ) |
|
112 |
|
113 /* {{-output"h263dDecodeFrame.txt"}} */ |
|
114 { |
|
115 TInt colorEffect = aDecoderInfo->aColorEffect; |
|
116 TInt colorToneU = aDecoderInfo->aColorToneU; |
|
117 TInt colorToneV = aDecoderInfo->aColorToneV; |
|
118 TInt frameOperation = aDecoderInfo->aFrameOperation; |
|
119 TInt* trP = aDecoderInfo->aTrP; |
|
120 TInt* trD = aDecoderInfo->aTrD; |
|
121 TInt videoClipNumber = aDecoderInfo->aVideoClipNumber; |
|
122 TInt smSpeed = aDecoderInfo->aSMSpeed; |
|
123 TInt getDecodedFrame = aDecoderInfo->aGetDecodedFrame; |
|
124 |
|
125 bibBuffer_t |
|
126 *buffer = 0; /* input buffer */ |
|
127 |
|
128 bibBuffer_t |
|
129 *outbuffer = 0; /* output buffer */ |
|
130 |
|
131 bibBuffer_t |
|
132 *tmpbuffer = 0; /* temporary buffer */ |
|
133 |
|
134 u_char* tmpbuf=0; |
|
135 |
|
136 bibBufferEdit_t |
|
137 *bufEdit = 0; |
|
138 |
|
139 int StartByteIndex=0; |
|
140 int StartBitIndex=7; |
|
141 |
|
142 int tr = 0; |
|
143 int newtr = 0; |
|
144 int efftr; |
|
145 int numBitsGot; |
|
146 int bitsErrorIndication; |
|
147 int16 bibError; |
|
148 |
|
149 int retValue; /* return value for vde functions */ |
|
150 |
|
151 int leaveError = 0; |
|
152 |
|
153 int16 |
|
154 errorCode = 0; /* return code for bib functions */ |
|
155 |
|
156 /* MVE */ |
|
157 int startCodeLen = 0; |
|
158 CMPEG4Transcoder *hTranscoder = NULL; |
|
159 |
|
160 TBool modifyMPEG4Afterwards = EFalse; |
|
161 |
|
162 vdeAssert(hInstance); |
|
163 vdeAssert(pStreamBuffer); |
|
164 vdeAssert(pOutStreamBuffer); |
|
165 vdeAssert(streamBufferSize); |
|
166 vdeAssert(fFirstFrame); |
|
167 |
|
168 vdeInstance_t *vdeinstance = (vdeInstance_t *) hInstance; |
|
169 |
|
170 /* Create bit buffer */ |
|
171 buffer = bibCreate(pStreamBuffer, streamBufferSize, &errorCode); |
|
172 if (!buffer || errorCode) |
|
173 return H263D_ERROR; |
|
174 |
|
175 /* MVE */ |
|
176 |
|
177 if ((aDecoderInfo->streamMode==EVedVideoBitstreamModeMPEG4ShortHeader) || (aDecoderInfo->streamMode == EVedVideoBitstreamModeH263) ) |
|
178 outbuffer = bibCreate(pOutStreamBuffer, streamBufferSize-3, &errorCode); |
|
179 else |
|
180 outbuffer = bibCreate(pOutStreamBuffer, streamBufferSize-4-3, &errorCode); |
|
181 |
|
182 if (!outbuffer || errorCode) |
|
183 { |
|
184 bibDelete(buffer, &errorCode); |
|
185 return H263D_ERROR; |
|
186 } |
|
187 |
|
188 bufEdit = bibBufferEditCreate(&errorCode); |
|
189 if (!bufEdit || errorCode) |
|
190 { |
|
191 bibDelete(outbuffer, &errorCode); |
|
192 bibDelete(buffer, &errorCode); |
|
193 return H263D_ERROR; |
|
194 } |
|
195 |
|
196 if(frameOperation==4 /*ENoDecodeNoWrite*/) |
|
197 { |
|
198 bufEdit->copyMode = CopyNone; |
|
199 } |
|
200 |
|
201 if(colorEffect==1 || colorEffect==2) |
|
202 { |
|
203 outbuffer->numBytesRead=0; |
|
204 outbuffer->size=0; |
|
205 } |
|
206 |
|
207 /* Associate bit buffer with the VDE instance */ |
|
208 retValue = vdeSetInputBuffer(hInstance, buffer); |
|
209 if (retValue < 0) |
|
210 goto freeBufferAndReturn; |
|
211 |
|
212 /* Associate output bit buffer with the VDE instance */ |
|
213 retValue = vdeSetOutputBuffer(hInstance, outbuffer); |
|
214 if (retValue < 0) |
|
215 goto freeBufferAndReturn; |
|
216 |
|
217 retValue = vdeSetBufferEdit(hInstance, bufEdit); |
|
218 if (retValue < 0) |
|
219 goto freeBufferAndReturn; |
|
220 |
|
221 retValue = vdeSetVideoEditParams(hInstance, colorEffect, |
|
222 getDecodedFrame, colorToneU, colorToneV); |
|
223 if (retValue < 0) |
|
224 goto freeBufferAndReturn; |
|
225 |
|
226 /* MVE */ |
|
227 if (aDecoderInfo->streamMode == EVedVideoBitstreamModeH263 /*H.263*/) |
|
228 { |
|
229 /* read current TR */ |
|
230 bibForwardBits(22,buffer); // streamBufferSize is in bytes |
|
231 tr = bibGetBits(8,buffer,&numBitsGot, &bitsErrorIndication, &bibError); |
|
232 bibRewindBits(30,buffer,&bibError); |
|
233 } |
|
234 |
|
235 /* get first frame's QP */ |
|
236 if (!(*fFirstFrame)) |
|
237 { |
|
238 vdeinstance->iRefQp = aDecoderInfo->aFirstFrameQp; |
|
239 } |
|
240 vdeinstance->iColorEffect = aDecoderInfo->aColorEffect; |
|
241 vdeinstance->iColorToneU = aDecoderInfo->aColorToneU; |
|
242 vdeinstance->iColorToneV = aDecoderInfo->aColorToneV; |
|
243 |
|
244 /* MVE */ |
|
245 /* one frame is ready, initialize the transcoder */ |
|
246 TRAP( leaveError, (hTranscoder = CMPEG4Transcoder::NewL(vdeinstance, vdeinstance->inBuffer, vdeinstance->outBuffer)) ); |
|
247 if ( leaveError != 0 ) |
|
248 { |
|
249 retValue = leaveError; |
|
250 goto freeBufferAndReturn; |
|
251 } |
|
252 |
|
253 if (aDecoderInfo->aGetVideoMode) |
|
254 { |
|
255 /* we are to determine the bitstream mode */ |
|
256 aDecoderInfo->aOutputVideoFormat = EVedVideoTypeNoVideo; |
|
257 int dummy1, dummy2; // position of the error resillence bit,not used here |
|
258 vdtGetVideoBitstreamInfo(buffer, aDecoderInfo, &dummy1, &dummy2); |
|
259 } |
|
260 |
|
261 /* set transcoding information */ |
|
262 retValue = hTranscoder->SetTranscoding(aDecoderInfo); |
|
263 if ( retValue != TX_OK ) |
|
264 { |
|
265 goto freeBufferAndReturn; |
|
266 } |
|
267 |
|
268 /* before the first frame is decoded, determine the stream type */ |
|
269 if (*fFirstFrame) { |
|
270 retValue = vdeDetermineStreamType(hInstance, hTranscoder); |
|
271 if (retValue < 0) |
|
272 goto freeBufferAndReturn; |
|
273 |
|
274 /* MVE */ |
|
275 /* for the first frame of the bitstream, we may need to construct a new VOS */ |
|
276 hTranscoder->ConstructVOSHeader(vdeinstance->fMPEG4, aDecoderInfo); |
|
277 |
|
278 if (vdeinstance->fMPEG4 == 1 ) |
|
279 { |
|
280 StartByteIndex = buffer->getIndex; |
|
281 StartBitIndex = buffer->bitIndex; |
|
282 |
|
283 /* for MPEG4 (not including shortheader) stuffing bits are inserted at the end of the VOS |
|
284 but the index here indicates the position of the stuffing bits |
|
285 */ |
|
286 if (StartBitIndex != 7) |
|
287 { |
|
288 StartByteIndex += 1; |
|
289 StartBitIndex = 7; |
|
290 } |
|
291 |
|
292 // update the output stream size by removing VOS size |
|
293 streamBufferSize -= StartByteIndex; |
|
294 } |
|
295 |
|
296 else if (aDecoderInfo->streamMode == EVedVideoBitstreamModeMPEG4ShortHeader) |
|
297 { |
|
298 if (aDecoderInfo->aOutputVideoFormat == EVedVideoTypeH263Profile0Level10 || |
|
299 aDecoderInfo->aOutputVideoFormat == EVedVideoTypeH263Profile0Level45) |
|
300 { |
|
301 // we don't need the VOS header |
|
302 StartByteIndex = buffer->getIndex; |
|
303 StartBitIndex = buffer->bitIndex; |
|
304 // update the output stream size by removing VOS size |
|
305 streamBufferSize -= StartByteIndex; |
|
306 } |
|
307 else if (aDecoderInfo->aOutputVideoFormat == EVedVideoTypeMPEG4SimpleProfile && |
|
308 aDecoderInfo->fModeChanged == EFalse) |
|
309 { |
|
310 // update the output stream size by removing VOS size |
|
311 // but we need the original MPEG4 shortheader VOS, which is not yet copied to the output buffer |
|
312 streamBufferSize -= buffer->getIndex; |
|
313 |
|
314 } |
|
315 } |
|
316 |
|
317 } |
|
318 |
|
319 /* This may produce multiple output frames, and that is why it is commented |
|
320 out. However, it may be useful if the bitstream is corrupted and picture |
|
321 start codes are lost |
|
322 while (buffer->bitsLeft > 8) { */ |
|
323 /* Decode frame */ |
|
324 |
|
325 /* MVE */ |
|
326 /* The buffer size is changed in h263decoder.cpp |
|
327 In the old version, it is fixed to 3, which may be incorrect |
|
328 */ |
|
329 startCodeLen = (aDecoderInfo->streamMode == EVedVideoBitstreamModeH263)? KH263StartCodeLength : KMPEG4StartCodeLength; |
|
330 |
|
331 |
|
332 |
|
333 if ( ((aDecoderInfo->aOutputVideoFormat == EVedVideoTypeMPEG4SimpleProfile) |
|
334 && !(aDecoderInfo->streamMode == EVedVideoBitstreamModeMPEG4ShortHeader)) |
|
335 || ((aDecoderInfo->streamMode == EVedVideoBitstreamModeMPEG4ShortHeader) && aDecoderInfo->fModeChanged) ) |
|
336 { |
|
337 modifyMPEG4Afterwards = ETrue; |
|
338 } |
|
339 |
|
340 if (frameOperation==1/*EDecodeAndWrite*/ || frameOperation==2/*EDecodeNoWrite*/) |
|
341 { |
|
342 if ( vdeinstance->fMPEG4 == 1 ) |
|
343 { |
|
344 buffer->size -= startCodeLen; |
|
345 buffer->bitsLeft -= ( startCodeLen << 3 ); |
|
346 } |
|
347 retValue = vdeDecodeFrame(hInstance, StartByteIndex, StartBitIndex, hTranscoder); |
|
348 if ( retValue < VDE_OK ) |
|
349 { |
|
350 // negative means fatal error |
|
351 goto freeBufferAndReturn; |
|
352 } |
|
353 // get first frame QP for possible color toning |
|
354 if (*fFirstFrame) |
|
355 { |
|
356 aDecoderInfo->aFirstFrameQp = hTranscoder->GetRefQP(); |
|
357 } |
|
358 } |
|
359 else if (frameOperation==3/*EWriteNoDecode*/) |
|
360 { |
|
361 /* first reset bit counter to beginning of buffer */ |
|
362 /* copy input frame as it is */ |
|
363 bibForwardBits((streamBufferSize-startCodeLen)<<3,buffer); // streamBufferSize is in bytes |
|
364 |
|
365 if (aDecoderInfo->streamMode == EVedVideoBitstreamModeMPEG4ShortHeader && |
|
366 aDecoderInfo->aOutputVideoFormat == EVedVideoTypeMPEG4SimpleProfile && |
|
367 !(aDecoderInfo->fModeChanged)) |
|
368 { |
|
369 bibRewindBits(32,buffer,&bibError); |
|
370 } |
|
371 |
|
372 /* reset buffer edit to CopyWhole mode */ |
|
373 bufEdit->copyMode = CopyWhole/*CopyWhole*/; |
|
374 |
|
375 if ( vdeinstance->fMPEG4 == 1 ) |
|
376 { |
|
377 if (*fFirstFrame) |
|
378 { |
|
379 buffer->getIndex = buffer->size - startCodeLen; |
|
380 buffer->bitIndex = 7; |
|
381 buffer->bitsLeft = 24; |
|
382 buffer->numBytesRead = buffer->size - startCodeLen; |
|
383 } |
|
384 |
|
385 if ( buffer->numBytesRead > 4 ) |
|
386 { |
|
387 buffer->numBytesRead -= 4; |
|
388 buffer->getIndex = buffer->numBytesRead; |
|
389 } |
|
390 } |
|
391 // Reassign pointers so that outbuffer actually has the pointer to (in)buffer's data, |
|
392 // if we have MPEG4 output (not short header) and we need to change e.g. timestamps |
|
393 // This eliminates 2 memory copies - otherwise we would copy from buffer to outbuffer to tmpbuffer to outbuffer; |
|
394 // the content is modified when copying from tmpbuffer to outbuffer. |
|
395 // tmpbuffer is needed since we can't modify the content directly in the outbuffer. |
|
396 // Now we can copy directly from buffer to outbuffer. |
|
397 // In this branch we don't call vdeDecodeFrame at all, but use either CopyEditVopL for MPEG-4 or |
|
398 // CopyStream for H.263 |
|
399 if ( modifyMPEG4Afterwards ) |
|
400 { |
|
401 tmpbuffer = buffer; |
|
402 } |
|
403 else |
|
404 { |
|
405 /* copy from buffer to outbuffer. This simulates vdeDecodeFrame with EDecodeAndWrite */ |
|
406 CopyStream(buffer,outbuffer,bufEdit,StartByteIndex,StartBitIndex); |
|
407 } |
|
408 retValue=0; |
|
409 } |
|
410 |
|
411 outbuffer->size = outbuffer->getIndex; |
|
412 outbuffer->bitsLeft = 0; |
|
413 |
|
414 if ( !tmpbuffer ) |
|
415 { |
|
416 /* if tr values are changes, need another buffer */ |
|
417 /* first create temp buffer in memory */ |
|
418 tmpbuf = (u_char*) malloc(outbuffer->size + 4); |
|
419 if (tmpbuf == NULL) |
|
420 { |
|
421 bibDelete(outbuffer, &errorCode); |
|
422 bibDelete(buffer, &errorCode); |
|
423 bibBufEditDelete(bufEdit, &errorCode); |
|
424 return H263D_ERROR; |
|
425 } |
|
426 tmpbuffer = bibCreate((void*)tmpbuf, outbuffer->size + 4, &errorCode); |
|
427 if (!tmpbuffer || errorCode) |
|
428 { |
|
429 free(tmpbuf); |
|
430 bibDelete(outbuffer, &errorCode); |
|
431 bibDelete(buffer, &errorCode); |
|
432 bibBufEditDelete(bufEdit, &errorCode); |
|
433 return H263D_ERROR; |
|
434 } |
|
435 } |
|
436 |
|
437 /* MVE */ |
|
438 if (aDecoderInfo->aOutputVideoFormat != EVedVideoTypeNoVideo) |
|
439 { |
|
440 |
|
441 if ( modifyMPEG4Afterwards ) |
|
442 { |
|
443 if ( tmpbuffer != buffer ) |
|
444 { |
|
445 // the bitstream was decoded too, need to copy it temporarily from outbuffer to tmpbuffer since it needs to be modified |
|
446 bibRewindBits(bibNumberOfFlushedBits(tmpbuffer),tmpbuffer,&bibError); |
|
447 bibRewindBits(bibNumberOfFlushedBits(outbuffer),outbuffer,&bibError); |
|
448 bibForwardBits(((outbuffer->size)<<3),outbuffer); |
|
449 outbuffer->bitsLeft = 0; |
|
450 |
|
451 StartByteIndex = 0; |
|
452 StartBitIndex = 7; |
|
453 |
|
454 CopyStream(outbuffer,tmpbuffer,bufEdit,StartByteIndex,StartBitIndex); |
|
455 tmpbuffer->baseAddr[tmpbuffer->getIndex] = 0x0; |
|
456 tmpbuffer->baseAddr[tmpbuffer->getIndex+1] = 0x0; |
|
457 tmpbuffer->baseAddr[tmpbuffer->getIndex+2] = 0x01; |
|
458 tmpbuffer->baseAddr[tmpbuffer->getIndex+3] = 0xb6; |
|
459 } |
|
460 else |
|
461 { |
|
462 // the tmpbuffer was used as a shortcut to the buffer, no need to copy anything here. |
|
463 tmpbuffer->bitsLeft = 32; |
|
464 // the following ones are probably not needed |
|
465 tmpbuffer->baseAddr[tmpbuffer->getIndex+4] = 0x0; |
|
466 tmpbuffer->baseAddr[tmpbuffer->getIndex+5] = 0x0; |
|
467 tmpbuffer->baseAddr[tmpbuffer->getIndex+6] = 0x01; |
|
468 tmpbuffer->baseAddr[tmpbuffer->getIndex+7] = 0xb6; |
|
469 } |
|
470 |
|
471 |
|
472 bibForwardBits(32,tmpbuffer); |
|
473 |
|
474 // Copy bitstream part-by-part, possibly modifying it, from tmp to output. |
|
475 // StartByteIndex may be > 0 if there is VOS header in tmpbuffer already. It is always byte-aligned so no need to have StartBitIndex |
|
476 TInt skip = 0; |
|
477 if ( StartByteIndex > 0 ) |
|
478 { |
|
479 // startByteIndex refers to input buffer. |
|
480 // The skip however should refer to the output buffer. The output header size is in aDecoderInfo |
|
481 skip = aDecoderInfo->vosHeaderSize; |
|
482 } |
|
483 int retVal= CopyEditVop(hInstance, skip, tmpbuffer, aDecoderInfo); |
|
484 if(retVal<0) |
|
485 { |
|
486 retValue = retVal; //will be handled later |
|
487 } |
|
488 } |
|
489 else |
|
490 { |
|
491 /* copy input frame while changing TR */ |
|
492 if((videoClipNumber>0) || (smSpeed!=1000)) |
|
493 { |
|
494 if ((frameOperation==1) || ((frameOperation==2) && !getDecodedFrame)) |
|
495 { |
|
496 /* if the output buffer will not be use, leave it as it is! */ |
|
497 } |
|
498 else |
|
499 { |
|
500 |
|
501 /* get new TR */ |
|
502 StartByteIndex = 0; |
|
503 StartBitIndex = 7; |
|
504 outbuffer->bitsLeft = 0; |
|
505 newtr = GetNewTrValue(tr, trP, trD, smSpeed); |
|
506 /* change TR value in output bitstream */ |
|
507 /* prepare editing position */ |
|
508 if (!bufEdit->editParams) |
|
509 { |
|
510 bufEdit->editParams = (bibEditParams_t *) malloc(sizeof(bibEditParams_t)); |
|
511 if (bufEdit->editParams == NULL) |
|
512 { |
|
513 retValue = H263D_ERROR; |
|
514 goto freeBufferAndReturn; |
|
515 } |
|
516 |
|
517 bufEdit->numChanges=1; |
|
518 bufEdit->copyMode = CopyWithEdit; // CopyWithEdit |
|
519 } |
|
520 bufEdit->editParams->curNumBits = bufEdit->editParams->newNumBits = 8; |
|
521 bufEdit->editParams->StartByteIndex=2; //2; // starting position for the TR marker |
|
522 bufEdit->editParams->StartBitIndex=1; //1; // starting position for the TR marker |
|
523 bufEdit->editParams->newValue=newtr; |
|
524 /* copy the input buffer to the output buffer with TR changes */ |
|
525 CopyStream(outbuffer,tmpbuffer,bufEdit,StartByteIndex,StartBitIndex); |
|
526 bibRewindBits((streamBufferSize)<<3,buffer,&bibError); |
|
527 /* copy the changed bitstream from tmpbuffer back to buffer */ |
|
528 bufEdit->copyMode = CopyWhole; // CopyWhole |
|
529 bibRewindBits(bibNumberOfFlushedBits(outbuffer),outbuffer,&bibError); |
|
530 CopyStream(tmpbuffer,outbuffer,bufEdit,StartByteIndex,StartBitIndex); |
|
531 bibRewindBits((streamBufferSize)<<3,buffer,&bibError); |
|
532 } |
|
533 } |
|
534 /* update TR values */ |
|
535 efftr = (videoClipNumber>0 || smSpeed!=1000) ? newtr : tr; |
|
536 *trP = efftr; |
|
537 *trD = tr; |
|
538 } |
|
539 } |
|
540 |
|
541 *fFirstFrame = 0; |
|
542 |
|
543 if (retValue < 0) |
|
544 goto freeBufferAndReturn; |
|
545 /* See the comment above. |
|
546 else if (retValue == H263D_OK_EOS) |
|
547 break; |
|
548 } */ |
|
549 |
|
550 if (frameSize) |
|
551 *frameSize = bibNumberOfFlushedBytes(buffer) + |
|
552 ((bibNumberOfFlushedBits(buffer) % 8 > 0) ? 1 : 0); |
|
553 |
|
554 *outframeSize = outbuffer->numBytesRead; |
|
555 |
|
556 |
|
557 freeBufferAndReturn: |
|
558 |
|
559 int bitError = buffer->error; |
|
560 |
|
561 if (hTranscoder) |
|
562 { |
|
563 delete hTranscoder; |
|
564 hTranscoder = NULL; |
|
565 } |
|
566 |
|
567 if ( tmpbuffer == buffer ) |
|
568 { |
|
569 // tmpbuffer was a shortcut to inbuffer, set it to NULL to avoid deleting it |
|
570 tmpbuffer = NULL; |
|
571 } |
|
572 |
|
573 int16 deleteError = 0; |
|
574 /* Delete bit buffer */ |
|
575 bibDelete(buffer, &errorCode); |
|
576 if ( errorCode ) |
|
577 { |
|
578 deleteError = errorCode; |
|
579 } |
|
580 |
|
581 /* Delete output bit buffer */ |
|
582 bibDelete(outbuffer, &errorCode); |
|
583 if ( errorCode ) |
|
584 { |
|
585 deleteError = errorCode; |
|
586 } |
|
587 |
|
588 /* Delete tmp bit buffer, if it was used */ |
|
589 if ( tmpbuffer ) |
|
590 { |
|
591 bibDelete(tmpbuffer, &errorCode); |
|
592 if ( errorCode ) |
|
593 { |
|
594 deleteError = errorCode; |
|
595 } |
|
596 } |
|
597 if(tmpbuf) |
|
598 free(tmpbuf); |
|
599 |
|
600 /* Delete bufEdit */ |
|
601 bibBufEditDelete(bufEdit, &errorCode); |
|
602 if ( errorCode ) |
|
603 { |
|
604 deleteError = errorCode; |
|
605 } |
|
606 if (deleteError || errorCode) |
|
607 return H263D_ERROR; |
|
608 |
|
609 if ( bitError ) |
|
610 { |
|
611 return H263D_OK_BUT_FRAME_USELESS; |
|
612 } |
|
613 |
|
614 return retValue; |
|
615 } |
|
616 |
|
617 |
|
618 /* {{-output"h263dGetLatestFrame.txt"}} */ |
|
619 /* |
|
620 * h263dGetLatestFrame |
|
621 * |
|
622 * |
|
623 * Parameters: |
|
624 * hInstance instance data |
|
625 * |
|
626 * ppy, ppu, ppv used to return Y, U and V frame pointers |
|
627 * |
|
628 * pLumWidth, pLumHeight used to return luminance image width and height |
|
629 * |
|
630 * pFrameNum used to return frame number |
|
631 * |
|
632 * Function: |
|
633 * This function returns the latest correctly decoded frame |
|
634 * (and some side-information). |
|
635 * |
|
636 * Returns: |
|
637 * H263D_OK if the function was successful |
|
638 * H263D_ERROR if a fatal error, from which the decoder |
|
639 * cannot be restored, has occured |
|
640 * H263D_ERROR_HALTED the instance is halted, it should be closed |
|
641 */ |
|
642 |
|
643 |
|
644 int H263D_CC h263dGetLatestFrame( |
|
645 h263dHInstance_t hInstance, |
|
646 u_char **ppy, u_char **ppu, u_char **ppv, |
|
647 int *pLumWidth, int *pLumHeight, |
|
648 int *pFrameNum) |
|
649 /* {{-output"h263dGetLatestFrame.txt"}} */ |
|
650 { |
|
651 vdeAssert(hInstance); |
|
652 vdeAssert(ppy); |
|
653 vdeAssert(ppu); |
|
654 vdeAssert(ppv); |
|
655 vdeAssert(pLumWidth); |
|
656 vdeAssert(pLumHeight); |
|
657 vdeAssert(pFrameNum); |
|
658 |
|
659 return vdeGetLatestFrame(hInstance, ppy, ppu, ppv, pLumWidth, pLumHeight, |
|
660 pFrameNum); |
|
661 } |
|
662 |
|
663 |
|
664 |
|
665 /* {{-output"h263dIsIntra.txt"}} */ |
|
666 /* |
|
667 * h263dIsIntra |
|
668 * |
|
669 * |
|
670 * Parameters: |
|
671 * hInstance handle of instance data |
|
672 * frameStart pointer to memory chunk containing a frame |
|
673 * frameLength number of bytes in frame |
|
674 * |
|
675 * Function: |
|
676 * This function returns 1 if the passed frame is an INTRA frame. |
|
677 * Otherwise the function returns 0. |
|
678 * |
|
679 * Returns: |
|
680 * See above. |
|
681 */ |
|
682 |
|
683 int h263dIsIntra( |
|
684 h263dHInstance_t hInstance, |
|
685 void *frameStart, |
|
686 unsigned frameLength) |
|
687 /* {{-output"h263dIsIntra.txt"}} */ |
|
688 { |
|
689 vdeAssert(hInstance); |
|
690 vdeAssert(frameStart); |
|
691 vdeAssert(frameLength); |
|
692 |
|
693 return vdeIsINTRA(hInstance, frameStart, frameLength); |
|
694 } |
|
695 |
|
696 /* {{-output"h263dOpen.txt"}} */ |
|
697 /* |
|
698 * h263dOpen |
|
699 * |
|
700 * |
|
701 * Parameters: |
|
702 * openParam initialization parameters |
|
703 * |
|
704 * Function: |
|
705 * This function creates and initializes a new H.263 decoder instance. |
|
706 * |
|
707 * Returns: |
|
708 * an instance handle if the function was successful |
|
709 * NULL if an error occured |
|
710 */ |
|
711 |
|
712 h263dHInstance_t H263D_CC h263dOpen(h263dOpen_t *openParam) |
|
713 /* {{-output"h263dOpen.txt"}} */ |
|
714 { |
|
715 vdeAssert(openParam); |
|
716 |
|
717 /* No extra space needs to be allocated after the VDE instance data |
|
718 (of type vdeInstance_t) due to the fact that no thread specific |
|
719 data is needed. */ |
|
720 openParam->freeSpace = 0; |
|
721 |
|
722 return vdeInit(openParam); |
|
723 } |
|
724 |
|
725 |
|
726 |
|
727 int GetNewTrValue(int aTrCurOrig, int* aTrPrevNew, int* aTrPrevOrig, int aSMSpeed) |
|
728 { |
|
729 int trCurNew=0; |
|
730 int trDiff=0; |
|
731 TReal speedFactor = (TReal)aSMSpeed/1000.0; |
|
732 |
|
733 trDiff = aTrCurOrig - *aTrPrevOrig; |
|
734 if(trDiff==0) // if corrupt TR values |
|
735 trDiff=1; |
|
736 else if(trDiff<0) // jump in TR values (change of clip or end of limit) |
|
737 trDiff = 3; // arbitrary, for 10 fps default |
|
738 // check for slow motion |
|
739 vdeAssert(aSMSpeed); |
|
740 if(aSMSpeed!=1000) |
|
741 trDiff = (int)((TReal)trDiff/speedFactor + 0.5); |
|
742 trCurNew = *aTrPrevNew + trDiff; |
|
743 if(trCurNew>255) |
|
744 trCurNew = trCurNew%256; |
|
745 return trCurNew; |
|
746 } |
|
747 |
|
748 |
|
749 |
|
750 // End of File |
|