blob: d351c8df0fc9e30809938c57bfeafda1845c1615
1 | /* ***** BEGIN LICENSE BLOCK ***** |
2 | * Source last modified: $Id: rv_depack_internal.c,v 1.1.1.1.2.1 2005/05/04 18:21:20 hubbe Exp $ |
3 | * |
4 | * REALNETWORKS CONFIDENTIAL--NOT FOR DISTRIBUTION IN SOURCE CODE FORM |
5 | * Portions Copyright (c) 1995-2005 RealNetworks, Inc. |
6 | * All Rights Reserved. |
7 | * |
8 | * The contents of this file, and the files included with this file, |
9 | * are subject to the current version of the Real Format Source Code |
10 | * Porting and Optimization License, available at |
11 | * https://helixcommunity.org/2005/license/realformatsource (unless |
12 | * RealNetworks otherwise expressly agrees in writing that you are |
13 | * subject to a different license). You may also obtain the license |
14 | * terms directly from RealNetworks. You may not use this file except |
15 | * in compliance with the Real Format Source Code Porting and |
16 | * Optimization License. There are no redistribution rights for the |
17 | * source code of this file. Please see the Real Format Source Code |
18 | * Porting and Optimization License for the rights, obligations and |
19 | * limitations governing use of the contents of the file. |
20 | * |
21 | * RealNetworks is the developer of the Original Code and owns the |
22 | * copyrights in the portions it created. |
23 | * |
24 | * This file, and the files included with this file, is distributed and |
25 | * made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, |
26 | * EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL |
27 | * SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF |
28 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT |
29 | * OR NON-INFRINGEMENT. |
30 | * |
31 | * Technology Compatibility Kit Test Suite(s) Location: |
32 | * https://rarvcode-tck.helixcommunity.org |
33 | * |
34 | * Contributor(s): |
35 | * |
36 | * ***** END LICENSE BLOCK ***** */ |
37 | |
38 | #include <stdio.h> |
39 | #include <string.h> |
40 | #include <memory.h> |
41 | //#include "includes.h" |
42 | #include "../include/helix_types.h" |
43 | #include "../include/helix_result.h" |
44 | #include "../include/pack_utils.h" |
45 | #include "../include/string_utils.h" |
46 | #include "../include/memory_utils.h" |
47 | #include "../include/packet_defines.h" |
48 | #include "../include/codec_defines.h" |
49 | #include "../include/stream_hdr_structs.h" |
50 | #include "../include/stream_hdr_utils.h" |
51 | #include "rv_depack_internal.h" |
52 | |
53 | #define RM_MAX_UINT14 0x00003FFF |
54 | #define RM_MAX_UINT30 0x3FFFFFFF |
55 | #define MAX_INTERNAL_TIMESTAMP_DELTA 60000 |
56 | |
57 | void* rv_depacki_malloc(rv_depack_internal* pInt, UINT32 ulSize) |
58 | { |
59 | void* pRet = HXNULL; |
60 | |
61 | if (pInt && pInt->fpMalloc) { |
62 | pRet = pInt->fpMalloc(pInt->pUserMem, ulSize); |
63 | } |
64 | |
65 | return pRet; |
66 | } |
67 | |
68 | void rv_depacki_free(rv_depack_internal* pInt, void* pMem) |
69 | { |
70 | if (pInt && pInt->fpFree) { |
71 | pInt->fpFree(pInt->pUserMem, pMem); |
72 | } |
73 | } |
74 | |
75 | HX_RESULT rv_depacki_init(rv_depack_internal* pInt, rm_stream_header* hdr) |
76 | { |
77 | HX_RESULT retVal = HXR_FAIL; |
78 | |
79 | if (pInt && hdr) { |
80 | /* Initialize local variables */ |
81 | UINT32 ulTmp = 0; |
82 | BYTE* pTmp = HXNULL; |
83 | UINT32 i = 0; |
84 | /* Check if we have a "HasRelativeTS" property - OK if we don't */ |
85 | if (HX_SUCCEEDED(rm_stream_get_property_int(hdr, "HasRelativeTS", &ulTmp))) { |
86 | pInt->bHasRelativeTimeStamps = (ulTmp ? TRUE : FALSE); |
87 | } |
88 | /* Check if we have a "ZeroTimeOffset" property - OK if we don't */ |
89 | if (HX_SUCCEEDED(rm_stream_get_property_int(hdr, "ZeroTimeOffset", &ulTmp))) { |
90 | pInt->ulZeroTimeOffset = ulTmp; |
91 | } |
92 | /* Check if we have a "RMFF 1.0 Flags" property */ |
93 | retVal = rm_stream_get_property_buf(hdr, "RMFF 1.0 Flags", &pTmp, &ulTmp); |
94 | if (retVal == HXR_OK) { |
95 | /* Unpack the rule2Flag map */ |
96 | rv_depacki_unpack_rule_map(pInt, &pInt->rule2Flag, &pTmp, &ulTmp); |
97 | /* Check if we have an "OpaqueData" property */ |
98 | retVal = rm_stream_get_property_buf(hdr, "OpaqueData", &pTmp, &ulTmp); |
99 | if (retVal == HXR_OK) { |
100 | /* Unpack the opaque data */ |
101 | retVal = rv_depacki_unpack_opaque_data(pInt, pTmp, ulTmp); |
102 | if (retVal == HXR_OK) { |
103 | /* |
104 | * Now that we've parsed all the headers, we need |
105 | * to see if there are any that need to be ignored. |
106 | * To do this, we parse the rules in the ASMRuleBook, |
107 | * and any rules that have "$OldPNMPlayer" as an expression, |
108 | * we will ignore. |
109 | */ |
110 | retVal = rv_depacki_check_rule_book(pInt, hdr); |
111 | if (retVal == HXR_OK) { |
112 | /* |
113 | * Now select the first non-ignored substream. If |
114 | * we are not surestream, this of course will be zero. |
115 | */ |
116 | pInt->ulActiveSubStream = 0; |
117 | if (pInt->bStreamSwitchable) { |
118 | for (i = 0; i < pInt->multiStreamHdr.ulNumSubStreams; i++) { |
119 | if (!pInt->bIgnoreSubStream[i]) { |
120 | pInt->ulActiveSubStream = i; |
121 | break; |
122 | } |
123 | } |
124 | } |
125 | } |
126 | } |
127 | } |
128 | } |
129 | } |
130 | |
131 | return retVal; |
132 | } |
133 | |
134 | HX_RESULT rv_depacki_unpack_rule_map(rv_depack_internal* pInt, |
135 | rm_rule_map* pMap, |
136 | BYTE** ppBuf, |
137 | UINT32* pulLen) |
138 | { |
139 | HX_RESULT retVal = HXR_FAIL; |
140 | |
141 | if (pInt) { |
142 | retVal = rm_unpack_rule_map(ppBuf, pulLen, |
143 | pInt->fpMalloc, |
144 | pInt->fpFree, |
145 | pInt->pUserMem, |
146 | pMap); |
147 | } |
148 | |
149 | return retVal; |
150 | } |
151 | |
152 | HX_RESULT rv_depacki_unpack_multistream_hdr(rv_depack_internal* pInt, |
153 | BYTE** ppBuf, |
154 | UINT32* pulLen) |
155 | { |
156 | HX_RESULT retVal = HXR_FAIL; |
157 | |
158 | if (pInt) { |
159 | retVal = rm_unpack_multistream_hdr(ppBuf, pulLen, |
160 | pInt->fpMalloc, |
161 | pInt->fpFree, |
162 | pInt->pUserMem, |
163 | &pInt->multiStreamHdr); |
164 | } |
165 | |
166 | return retVal; |
167 | } |
168 | |
169 | HX_RESULT rv_depacki_unpack_opaque_data(rv_depack_internal* pInt, |
170 | BYTE* pBuf, |
171 | UINT32 ulLen) |
172 | { |
173 | HX_RESULT retVal = HXR_FAIL; |
174 | |
175 | if (pInt && pBuf && ulLen >= 4) { |
176 | /* Initialize local variables */ |
177 | UINT32 ulSize = 0; |
178 | UINT32 ulID = 0; |
179 | UINT32 i = 0; |
180 | /* |
181 | * If the first four bytes are MLTI, then we |
182 | * know the opaque data contains a multistream header |
183 | * followed by several normal headers. So first we |
184 | * need to check the first four bytes. |
185 | */ |
186 | ulID = rm_unpack32(&pBuf, &ulLen); |
187 | /* Now back up 4 bytes */ |
188 | pBuf -= 4; |
189 | ulLen += 4; |
190 | /* Is this a multistream header? */ |
191 | if (ulID == RM_MULTIHEADER_OBJECT) { |
192 | /* Unpack the multistream header */ |
193 | retVal = rv_depacki_unpack_multistream_hdr(pInt, &pBuf, &ulLen); |
194 | if (retVal == HXR_OK) { |
195 | pInt->bStreamSwitchable = TRUE; |
196 | } |
197 | } else { |
198 | /* Single-rate stream */ |
199 | pInt->multiStreamHdr.ulNumSubStreams = 1; |
200 | /* Clear the stream switchable flag */ |
201 | pInt->bStreamSwitchable = FALSE; |
202 | /* Clear the return value */ |
203 | retVal = HXR_OK; |
204 | } |
205 | /* Clean up any existing substream header array */ |
206 | rv_depacki_cleanup_format_info_array(pInt); |
207 | /* Set the return value */ |
208 | retVal = HXR_FAIL; |
209 | /* Allocate space for substream header array */ |
210 | ulSize = pInt->multiStreamHdr.ulNumSubStreams * sizeof(rv_format_info); |
211 | pInt->pSubStreamHdr = (rv_format_info*) rv_depacki_malloc(pInt, ulSize); |
212 | if (pInt->pSubStreamHdr) { |
213 | /* NULL out the memory */ |
214 | memset(pInt->pSubStreamHdr, 0, ulSize); |
215 | /* Clear the return value */ |
216 | retVal = HXR_OK; |
217 | /* Loop through and unpack each substream header */ |
218 | for (i = 0; i < pInt->multiStreamHdr.ulNumSubStreams && retVal == HXR_OK; i++) { |
219 | /* Is this a multiheader? */ |
220 | if (pInt->bStreamSwitchable) { |
221 | /* |
222 | * If this is a multistream header, then there |
223 | * is a 4-byte length in front of every substream header |
224 | */ |
225 | if (ulLen >= 4) { |
226 | ulSize = rm_unpack32(&pBuf, &ulLen); |
227 | } else { |
228 | retVal = HXR_FAIL; |
229 | } |
230 | } |
231 | /* Now unpack an substream header */ |
232 | retVal = rv_depacki_unpack_format_info(pInt, |
233 | &pInt->pSubStreamHdr[i], |
234 | &pBuf, &ulLen); |
235 | } |
236 | } |
237 | } |
238 | |
239 | return retVal; |
240 | } |
241 | |
242 | void rv_depacki_cleanup_format_info(rv_depack_internal* pInt, |
243 | rv_format_info* pInfo) |
244 | { |
245 | if (pInt && pInfo && pInfo->pOpaqueData) { |
246 | rv_depacki_free(pInt, pInfo->pOpaqueData); |
247 | pInfo->pOpaqueData = HXNULL; |
248 | pInfo->ulOpaqueDataSize = 0; |
249 | } |
250 | } |
251 | |
252 | void rv_depacki_cleanup_format_info_array(rv_depack_internal* pInt) |
253 | { |
254 | if (pInt && pInt->pSubStreamHdr) { |
255 | /* Clean up each individual rv_format_info */ |
256 | UINT32 i = 0; |
257 | for (i = 0; i < pInt->multiStreamHdr.ulNumSubStreams; i++) { |
258 | rv_depacki_cleanup_format_info(pInt, &pInt->pSubStreamHdr[i]); |
259 | } |
260 | /* Clean up the array */ |
261 | rv_depacki_free(pInt, pInt->pSubStreamHdr); |
262 | pInt->pSubStreamHdr = HXNULL; |
263 | } |
264 | } |
265 | |
266 | HX_RESULT rv_depacki_unpack_format_info(rv_depack_internal* pInt, |
267 | rv_format_info* pInfo, |
268 | BYTE** ppBuf, |
269 | UINT32* pulLen) |
270 | { |
271 | HX_RESULT retVal = HXR_FAIL; |
272 | |
273 | if (pInt && pInfo && ppBuf && *ppBuf && pulLen && *pulLen >= 26) { |
274 | /* Clean up any existing opaque data */ |
275 | rv_depacki_cleanup_format_info(pInt, pInfo); |
276 | /* Unpack the format info struct */ |
277 | pInfo->ulLength = rm_unpack32(ppBuf, pulLen); |
278 | pInfo->ulMOFTag = rm_unpack32(ppBuf, pulLen); |
279 | pInfo->ulSubMOFTag = rm_unpack32(ppBuf, pulLen); |
280 | pInfo->usWidth = rm_unpack16(ppBuf, pulLen); |
281 | pInfo->usHeight = rm_unpack16(ppBuf, pulLen); |
282 | pInfo->usBitCount = rm_unpack16(ppBuf, pulLen); |
283 | pInfo->usPadWidth = rm_unpack16(ppBuf, pulLen); |
284 | pInfo->usPadHeight = rm_unpack16(ppBuf, pulLen); |
285 | pInfo->ufFramesPerSecond = rm_unpack32(ppBuf, pulLen); |
286 | /* Fix up the subMOF tag */ |
287 | if (pInfo->ulSubMOFTag == HX_RVTRVIDEO_ID) { |
288 | pInfo->ulSubMOFTag = HX_RV20VIDEO_ID; |
289 | } else if (pInfo->ulSubMOFTag == HX_RVTR_RV30_ID) { |
290 | pInfo->ulSubMOFTag = HX_RV30VIDEO_ID; |
291 | } |
292 | /* Compute the size of the opaque data */ |
293 | pInfo->ulOpaqueDataSize = pInfo->ulLength - 26; |
294 | /* Make sure we have enough left in the parsing buffer */ |
295 | if (*pulLen >= pInfo->ulOpaqueDataSize) { |
296 | /* Allocate a buffer of this size */ |
297 | pInfo->pOpaqueData = (BYTE*) rv_depacki_malloc(pInt, pInfo->ulOpaqueDataSize); |
298 | if (pInfo->pOpaqueData) { |
299 | /* Copy the buffer */ |
300 | memcpy(pInfo->pOpaqueData, *ppBuf, pInfo->ulOpaqueDataSize); |
301 | /* Advance the buffer */ |
302 | *ppBuf += pInfo->ulOpaqueDataSize; |
303 | *pulLen -= pInfo->ulOpaqueDataSize; |
304 | /* Clear the return value */ |
305 | retVal = HXR_OK; |
306 | } |
307 | } |
308 | } |
309 | |
310 | return retVal; |
311 | } |
312 | |
313 | HX_RESULT rv_depacki_check_rule_book(rv_depack_internal* pInt, rm_stream_header* hdr) |
314 | { |
315 | HX_RESULT retVal = HXR_FAIL; |
316 | |
317 | if (pInt && hdr) { |
318 | UINT32 ulSize = 0; |
319 | HXBOOL* pTmp = HXNULL; |
320 | char* pszRuleBook = HXNULL; |
321 | char* pStr = HXNULL; |
322 | char* pStrLimit = HXNULL; |
323 | UINT32 ulRule = 0; |
324 | UINT32 ulSubStream = 0; |
325 | const char* pszPNMStr = "$OldPNMPlayer"; |
326 | UINT32 ulPNMStrLen = strlen(pszPNMStr); |
327 | UINT32 ulNumRules = pInt->multiStreamHdr.rule2SubStream.ulNumRules; |
328 | UINT32 ulNumSubStreams = pInt->multiStreamHdr.ulNumSubStreams; |
329 | /* Is this SureStream? */ |
330 | if (pInt->bStreamSwitchable) { |
331 | /* Get the ASM Rule book */ |
332 | retVal = rm_stream_get_property_str(hdr, "ASMRuleBook", &pszRuleBook); |
333 | if (retVal == HXR_OK) { |
334 | /* Allocate space for the ignore header flags */ |
335 | ulSize = ulNumSubStreams * sizeof(HXBOOL); |
336 | pInt->bIgnoreSubStream = (HXBOOL*) rv_depacki_malloc(pInt, ulSize); |
337 | if (pInt->bIgnoreSubStream) { |
338 | /* NULL out the memory */ |
339 | memset(pInt->bIgnoreSubStream, 0, ulSize); |
340 | /* Allocate space for temporary boolean array */ |
341 | ulSize = ulNumRules * sizeof(HXBOOL); |
342 | pTmp = (HXBOOL*) rv_depacki_malloc(pInt, ulSize); |
343 | if (pTmp) { |
344 | /* NULL out the array */ |
345 | memset(pTmp, 0, ulSize); |
346 | /* Parse the string */ |
347 | pStr = pszRuleBook; |
348 | pStrLimit = pszRuleBook + strlen(pszRuleBook); |
349 | ulRule = 0; |
350 | while (pStr < pStrLimit && *pStr) { |
351 | while (pStr < pStrLimit && *pStr != ';') { |
352 | /* ignore quoted strings */ |
353 | if (*pStr == '"') { |
354 | /* step past open quote */ |
355 | pStr++; |
356 | /* ignore the string */ |
357 | while (pStr < pStrLimit && *pStr != '"') { |
358 | pStr++; |
359 | } |
360 | /* step past end quote occurs at bottom of while !';' loop. */ |
361 | } |
362 | |
363 | if (pStr + ulPNMStrLen < pStrLimit && *pStr == '$') { |
364 | /* check to see if we have a $OldPNMPlayer variable */ |
365 | if (!strncasecmp(pszPNMStr, pStr, ulPNMStrLen)) { |
366 | pStr += ulPNMStrLen; |
367 | pTmp[ulRule] = TRUE; |
368 | } |
369 | } |
370 | pStr++; |
371 | } |
372 | /* step past the ';' */ |
373 | pStr++; |
374 | /* next rule */ |
375 | ulRule++; |
376 | } |
377 | /* |
378 | * Now if pTmp[i] == TRUE, then we should ignore the |
379 | * substreams which correspond to rule i |
380 | */ |
381 | for (ulRule = 0; ulRule < ulNumRules; ulRule++) { |
382 | ulSubStream = rv_depacki_rule_to_substream(pInt, ulRule); |
383 | if (ulSubStream < ulNumSubStreams) { |
384 | pInt->bIgnoreSubStream[ulSubStream] = pTmp[ulRule]; |
385 | } |
386 | } |
387 | } |
388 | } |
389 | } |
390 | } else { |
391 | /* Not an error */ |
392 | retVal = HXR_OK; |
393 | } |
394 | } |
395 | |
396 | return retVal; |
397 | } |
398 | |
399 | HX_RESULT rv_depacki_copy_format_info(rv_depack_internal* pInt, |
400 | rv_format_info* pSrc, |
401 | rv_format_info* pDst) |
402 | { |
403 | HX_RESULT retVal = HXR_FAIL; |
404 | |
405 | if (pInt && pSrc && pDst) { |
406 | /* Clean up any existing format info */ |
407 | rv_depacki_cleanup_format_info(pInt, pDst); |
408 | /* Copy the members */ |
409 | pDst->ulLength = pSrc->ulLength; |
410 | pDst->ulMOFTag = pSrc->ulMOFTag; |
411 | pDst->ulSubMOFTag = pSrc->ulSubMOFTag; |
412 | pDst->usWidth = pSrc->usWidth; |
413 | pDst->usHeight = pSrc->usHeight; |
414 | pDst->usBitCount = pSrc->usBitCount; |
415 | pDst->usPadWidth = pSrc->usPadWidth; |
416 | pDst->usPadHeight = pSrc->usPadHeight; |
417 | pDst->ufFramesPerSecond = pSrc->ufFramesPerSecond; |
418 | pDst->ulOpaqueDataSize = pSrc->ulOpaqueDataSize; |
419 | /* Copy the opaque data buffer */ |
420 | pDst->pOpaqueData = copy_buffer(pInt->pUserMem, |
421 | pInt->fpMalloc, |
422 | pSrc->pOpaqueData, |
423 | pSrc->ulOpaqueDataSize); |
424 | if (pDst->pOpaqueData) { |
425 | /* Clear the return value */ |
426 | retVal = HXR_OK; |
427 | } |
428 | } |
429 | |
430 | return retVal; |
431 | } |
432 | |
433 | HX_RESULT rv_depacki_add_packet(rv_depack_internal* pInt, |
434 | rm_packet* pPacket) |
435 | { |
436 | HX_RESULT retVal = HXR_FAIL; |
437 | |
438 | if (pInt && pPacket) { |
439 | /* Init local variables */ |
440 | BYTE* pBuf = pPacket->pData; |
441 | UINT32 ulLen = (UINT32) pPacket->usDataLen; |
442 | UINT32 ulSubStream = 0; |
443 | rv_frame_hdr hdr; |
444 | /* Clear the return value */ |
445 | retVal = HXR_OK; |
446 | /* Make sure we are not ignoring this substream */ |
447 | ulSubStream = rv_depacki_rule_to_substream(pInt, pPacket->ucASMRule); |
448 | if (!pInt->bStreamSwitchable || |
449 | !pInt->bIgnoreSubStream[ulSubStream]) { |
450 | /* Loop through the packet buffer */ |
451 | while (ulLen && retVal == HXR_OK) { |
452 | /* Parse the current point in the packet buffer */ |
453 | retVal = rv_depacki_parse_frame_header(pInt, &pBuf, &ulLen, pPacket, &hdr); |
454 | if (retVal == HXR_OK) { |
455 | /* Switch based on frame header type */ |
456 | switch (hdr.eType) { |
457 | case RVFrameTypePartial: |
458 | case RVFrameTypeLastPartial: |
459 | retVal = rv_depacki_handle_partial(pInt, &pBuf, &ulLen, pPacket, &hdr); |
460 | break; |
461 | case RVFrameTypeMultiple: |
462 | case RVFrameTypeWhole: |
463 | retVal = rv_depacki_handle_one_frame(pInt, &pBuf, &ulLen, pPacket, &hdr); |
464 | break; |
465 | } |
466 | } |
467 | } |
468 | } |
469 | } |
470 | |
471 | return retVal; |
472 | } |
473 | |
474 | UINT32 rv_depacki_rule_to_flags(rv_depack_internal* pInt, UINT32 ulRule) |
475 | { |
476 | UINT32 ulRet = 0; |
477 | |
478 | if (pInt && |
479 | pInt->rule2Flag.pulMap && |
480 | ulRule < pInt->rule2Flag.ulNumRules) { |
481 | ulRet = pInt->rule2Flag.pulMap[ulRule]; |
482 | } |
483 | |
484 | return ulRet; |
485 | } |
486 | |
487 | UINT32 rv_depacki_rule_to_substream(rv_depack_internal* pInt, UINT32 ulRule) |
488 | { |
489 | UINT32 ulRet = 0; |
490 | |
491 | if (pInt && |
492 | pInt->multiStreamHdr.rule2SubStream.pulMap && |
493 | ulRule < pInt->multiStreamHdr.rule2SubStream.ulNumRules) { |
494 | ulRet = pInt->multiStreamHdr.rule2SubStream.pulMap[ulRule]; |
495 | } |
496 | |
497 | return ulRet; |
498 | } |
499 | |
500 | HX_RESULT rv_depacki_parse_frame_header(rv_depack_internal* pInt, |
501 | BYTE** ppBuf, |
502 | UINT32* pulLen, |
503 | rm_packet* pPacket, |
504 | rv_frame_hdr* pFrameHdr) |
505 | { |
506 | HX_RESULT retVal = HXR_FAIL; |
507 | |
508 | if (pInt && ppBuf && pulLen && pFrameHdr && *pulLen >= 2 && |
509 | *ppBuf >= pPacket->pData && |
510 | *ppBuf < pPacket->pData + pPacket->usDataLen) { |
511 | /* Initialize local variables */ |
512 | UINT32 ulTmp = 0; |
513 | HXBOOL bTmp = FALSE; |
514 | UINT32 ulOrigPacketTimeStamp = 0; |
515 | UINT32 ulClippedPacketTS = 0; |
516 | UINT32 ulDelta = 0; |
517 | BYTE* pBufAtStart = *ppBuf; |
518 | /* Set the offset of the header in the packet */ |
519 | pFrameHdr->ulHeaderOffset = pBufAtStart - pPacket->pData; |
520 | /* Parse the RVFrameType */ |
521 | pFrameHdr->eType = (RVFrameType)((pBufAtStart[0] & 0xC0) >> 6); |
522 | /* Switch based on frame type */ |
523 | switch (pFrameHdr->eType) { |
524 | case RVFrameTypePartial: |
525 | case RVFrameTypeLastPartial: |
526 | /* Unpack the bit field */ |
527 | ulTmp = rm_unpack16(ppBuf, pulLen); |
528 | pFrameHdr->ulNumPackets = ((ulTmp & 0x00003F80) >> 7); |
529 | pFrameHdr->ulPacketNum = (ulTmp & 0x0000007F); |
530 | /* Read the frame size */ |
531 | retVal = rv_depacki_read_14_or_30(ppBuf, pulLen, |
532 | &pFrameHdr->bBrokenUpByUs, |
533 | &pFrameHdr->ulFrameSize); |
534 | if (retVal == HXR_OK) { |
535 | /* Read the partial size or offset */ |
536 | ulTmp = 0; |
537 | retVal = rv_depacki_read_14_or_30(ppBuf, pulLen, &bTmp, &ulTmp); |
538 | if (retVal == HXR_OK) { |
539 | /* Make sure we have one byte */ |
540 | if (*pulLen >= 1) { |
541 | /* Get the sequence number */ |
542 | pFrameHdr->ulSeqNum = rm_unpack8(ppBuf, pulLen); |
543 | /* Assign the timestamp */ |
544 | pFrameHdr->ulTimestamp = pPacket->ulTime; |
545 | /* Compute the header size */ |
546 | pFrameHdr->ulHeaderSize = *ppBuf - pBufAtStart; |
547 | /* Assign the partial frame size and the partial frame offset. */ |
548 | if (pFrameHdr->eType == RVFrameTypePartial) { |
549 | /* |
550 | * For partial frames the partial_size_or_offset |
551 | * member contains the offset into the frame. The size |
552 | * of the partial frame is just the amount of data |
553 | * in the packet minus the header size. |
554 | */ |
555 | pFrameHdr->ulPartialFrameOffset = ulTmp; |
556 | pFrameHdr->ulPartialFrameSize = ((UINT32) pPacket->usDataLen) - |
557 | pFrameHdr->ulHeaderSize; |
558 | } else { |
559 | /* |
560 | * For last-partial frames, there could be other frame |
561 | * data after this, so the partial_size_or_offset field |
562 | * contains the partial frame size, not offset. We then |
563 | * compute the offset by subtracting the overall frame |
564 | * size from the partial frame size. |
565 | */ |
566 | pFrameHdr->ulPartialFrameSize = ulTmp; |
567 | pFrameHdr->ulPartialFrameOffset = pFrameHdr->ulFrameSize - ulTmp; |
568 | } |
569 | } else { |
570 | retVal = HXR_FAIL; |
571 | } |
572 | } |
573 | } |
574 | break; |
575 | case RVFrameTypeWhole: |
576 | /* Skip the one-byte frame type */ |
577 | rm_unpack8(ppBuf, pulLen); |
578 | /* Unpack the sequence number */ |
579 | pFrameHdr->ulSeqNum = rm_unpack8(ppBuf, pulLen); |
580 | /* Compute the header size */ |
581 | pFrameHdr->ulHeaderSize = *ppBuf - pBufAtStart; |
582 | /* Assign the frame header members */ |
583 | pFrameHdr->ulNumPackets = 1; |
584 | pFrameHdr->ulPacketNum = 1; |
585 | pFrameHdr->ulFrameSize = ((UINT32) pPacket->usDataLen) - |
586 | pFrameHdr->ulHeaderSize; |
587 | pFrameHdr->ulTimestamp = pPacket->ulTime; |
588 | pFrameHdr->bBrokenUpByUs = FALSE; |
589 | pFrameHdr->ulPartialFrameOffset = 0; |
590 | pFrameHdr->ulPartialFrameSize = 0; |
591 | /* Clear return value */ |
592 | retVal = HXR_OK; |
593 | break; |
594 | case RVFrameTypeMultiple: |
595 | /* |
596 | * For multiple frames, we still set ulNumPackets |
597 | * and ulPacketNum to 1, even though we know |
598 | * there are multiple packets. |
599 | */ |
600 | pFrameHdr->ulNumPackets = 1; |
601 | pFrameHdr->ulPacketNum = 1; |
602 | /* Skip the frame type */ |
603 | rm_unpack8(ppBuf, pulLen); |
604 | /* Unpack the frame size */ |
605 | retVal = rv_depacki_read_14_or_30(ppBuf, pulLen, &bTmp, |
606 | &pFrameHdr->ulFrameSize); |
607 | if (retVal == HXR_OK) { |
608 | /* For multiple frames, there is no partial size or offset */ |
609 | pFrameHdr->ulPartialFrameOffset = 0; |
610 | pFrameHdr->ulPartialFrameSize = 0; |
611 | /* Unpack the timestamp */ |
612 | retVal = rv_depacki_read_14_or_30(ppBuf, pulLen, &bTmp, |
613 | &pFrameHdr->ulTimestamp); |
614 | if (retVal == HXR_OK) { |
615 | /* Does this stream have relative timestamps? */ |
616 | if (pInt->bHasRelativeTimeStamps) { |
617 | /* |
618 | * Yes, we have relative timestamps so offset |
619 | * the timestamp in the frame header by the |
620 | * packet timestamp. |
621 | */ |
622 | pFrameHdr->ulTimestamp += pPacket->ulTime; |
623 | } else { |
624 | /* No relative timestamps */ |
625 | ulOrigPacketTimeStamp = pPacket->ulTime + pInt->ulZeroTimeOffset; |
626 | /* |
627 | * Because of a bug in the original Write14or30() which didn't mask |
628 | * the high bytes of the timestamp before |ing them with the flags, |
629 | * it's possible to read frame headers that are screwed up. If the |
630 | * application using this class sets the timestamp of the network packet |
631 | * before unpacking the header, we can determine if this header is |
632 | * screwed up and fix it. |
633 | */ |
634 | /* |
635 | * If the time stamp returned is less than the packet timestamp |
636 | * something is screwed up. If the packet timestamp is > 14 bits, |
637 | * the frame timestamp is < the packet timestamp and the packet |
638 | * timestamp is < 14 bits then the Write14or30 bug described above |
639 | * may have occured. It's possible for rollover to occur and trigger |
640 | * this so we check for that too. If the bug occured, we want to read 30 bits. |
641 | */ |
642 | if (ulOrigPacketTimeStamp > RM_MAX_UINT14 && |
643 | ulOrigPacketTimeStamp > pFrameHdr->ulTimestamp && |
644 | pFrameHdr->ulTimestamp < RM_MAX_UINT14 && |
645 | /* |
646 | * check for rollover. If we assume ulOrigPacketTimeStamp is from before |
647 | * rollover and m_ulTimeStamp is from after, the left hand expression below |
648 | * should be a small number because m_ulPacketTimeSamp will be close to |
649 | * MAX_UINT30 and m_ulTimeStamp will be close to 0. I chose 60 seconds |
650 | * since two frames 60 seconds appart shouldn't be in the same packet |
651 | * due to latency considerations in the encoder. JEFFA 4/28/99 |
652 | */ |
653 | !(((RM_MAX_UINT30 - ulOrigPacketTimeStamp) + pFrameHdr->ulTimestamp) <= 60000UL)) { |
654 | /* We should have read 14 bits, so back up 2 bytes */ |
655 | *ppBuf -= 2; |
656 | *pulLen += 2; |
657 | /* Now read 32 bits instead */ |
658 | pFrameHdr->ulTimestamp = rm_unpack32(ppBuf, pulLen); |
659 | } |
660 | |
661 | /* Clip the timestamp at 30 bits */ |
662 | ulClippedPacketTS = (ulOrigPacketTimeStamp & RM_MAX_UINT30); |
663 | /* |
664 | * Much code in the system assumes full 32 bit typestamps; reconstruct |
665 | * them here. We assume child timestamps are no more than 2^30 - 1 away |
666 | */ |
667 | ulDelta = (pFrameHdr->ulTimestamp >= ulClippedPacketTS ? |
668 | pFrameHdr->ulTimestamp - ulClippedPacketTS : |
669 | RM_MAX_UINT30 - ulClippedPacketTS + pFrameHdr->ulTimestamp); |
670 | pFrameHdr->ulTimestamp = ulOrigPacketTimeStamp + ulDelta; |
671 | /* If we have a zero time offset, we need to offset this timestamp */ |
672 | pFrameHdr->ulTimestamp -= pInt->ulZeroTimeOffset; |
673 | |
674 | /* |
675 | * Ensure that we have not caused the timestamp to fall behind |
676 | * the packet timestamp when we have subtracted zero time offset |
677 | */ |
678 | if (pInt->ulZeroTimeOffset && |
679 | (((INT32) pFrameHdr->ulTimestamp) - ((INT32) pPacket->ulTime) < 0)) { |
680 | pFrameHdr->ulTimestamp = pPacket->ulTime; |
681 | } |
682 | |
683 | /* |
684 | * If older rmffplin is serving this slta stream and internal |
685 | * frame timestamp is much larger than pkt timestamp, then |
686 | * we are dealing with un-translated-for-slta-live internal |
687 | * frame timestamps (the above calculation w/ ulDelta made |
688 | * super-small timestamps into super-large ones). Here, we |
689 | * adjust and make the internal timestamp equal to the pkt timestamp |
690 | */ |
691 | if (pFrameHdr->ulTimestamp - pPacket->ulTime > MAX_INTERNAL_TIMESTAMP_DELTA) { |
692 | pFrameHdr->ulTimestamp = pPacket->ulTime; |
693 | } |
694 | } |
695 | /* Read the sequence number */ |
696 | pFrameHdr->ulSeqNum = rm_unpack8(ppBuf, pulLen); |
697 | } |
698 | } |
699 | break; |
700 | } |
701 | if (retVal == HXR_OK) { |
702 | /* Compute the number of bytes in the frame header we just parsed. */ |
703 | pFrameHdr->ulHeaderSize = *ppBuf - pBufAtStart; |
704 | } |
705 | } |
706 | |
707 | return retVal; |
708 | } |
709 | |
710 | HX_RESULT rv_depacki_read_14_or_30(BYTE** ppBuf, |
711 | UINT32* pulLen, |
712 | HXBOOL* pbHiBit, |
713 | UINT32* pulValue) |
714 | { |
715 | HX_RESULT retVal = HXR_FAIL; |
716 | |
717 | if (ppBuf && pulLen && pbHiBit && pulValue && *ppBuf && *pulLen >= 2) { |
718 | /* Init local variables */ |
719 | UINT32 ulTmp = (*ppBuf)[0]; |
720 | /* Assign the high bit */ |
721 | *pbHiBit = ((ulTmp & 0x80) ? TRUE : FALSE); |
722 | /* |
723 | * Check the length bit. If it's 1, then |
724 | * this is a 14-bit value. If it's 0, then |
725 | * this is a 30-bit value. |
726 | */ |
727 | if (ulTmp & 0x40) { |
728 | /* |
729 | * This is a 14-bit value, so unpack 16 bits. |
730 | * We don't need to check the buffer size, since |
731 | * we already checked for a minimum of 2 bytes above. |
732 | */ |
733 | ulTmp = rm_unpack16(ppBuf, pulLen); |
734 | /* Mask out the upper two bits */ |
735 | *pulValue = (ulTmp & 0x00003FFF); |
736 | /* Clear the return value */ |
737 | retVal = HXR_OK; |
738 | } else { |
739 | /* This is a 30-bit value, so check size */ |
740 | if (*pulLen >= 4) { |
741 | /* Unpack 32 bits */ |
742 | ulTmp = rm_unpack32(ppBuf, pulLen); |
743 | /* Mask out the upper 2 bits */ |
744 | *pulValue = (ulTmp & 0x3FFFFFFF); |
745 | /* Clear the return value */ |
746 | retVal = HXR_OK; |
747 | } |
748 | } |
749 | } |
750 | |
751 | return retVal; |
752 | } |
753 | |
754 | HX_RESULT rv_depacki_handle_partial(rv_depack_internal* pInt, |
755 | BYTE** ppBuf, |
756 | UINT32* pulLen, |
757 | rm_packet* pPacket, |
758 | rv_frame_hdr* pFrameHdr) |
759 | { |
760 | HX_RESULT retVal = HXR_FAIL; |
761 | |
762 | if (pInt && ppBuf && pulLen && pPacket && pFrameHdr && *ppBuf) { |
763 | /* Init local variables */ |
764 | UINT32 i = 0; |
765 | UINT32 ulOffset = 0; |
766 | HXBOOL bAllThere = FALSE; |
767 | /* Clear the reutrn value */ |
768 | retVal = HXR_OK; |
769 | /* |
770 | * If we have a current frame and its timestamp |
771 | * is different from the packet timestamp, |
772 | * then we will send it. |
773 | */ |
774 | if (pInt->pCurFrame && |
775 | pInt->pCurFrame->ulTimestamp != pPacket->ulTime) { |
776 | /* Send the current frame */ |
777 | retVal = rv_depacki_send_current_frame(pInt); |
778 | } |
779 | /* Do we have a current frame? */ |
780 | if (retVal == HXR_OK && !pInt->pCurFrame) { |
781 | /* We don't have a current frame, so create one */ |
782 | retVal = rv_depacki_create_frame(pInt, pPacket, pFrameHdr, |
783 | &pInt->pCurFrame); |
784 | } |
785 | if (retVal == HXR_OK) { |
786 | /* Set the return value */ |
787 | retVal = HXR_FAIL; |
788 | /* Sanity check */ |
789 | ulOffset = pFrameHdr->ulPartialFrameOffset + pFrameHdr->ulPartialFrameSize; |
790 | if (ulOffset <= pInt->pCurFrame->ulDataLen && |
791 | *pulLen >= pFrameHdr->ulPartialFrameSize && |
792 | pFrameHdr->ulPacketNum - 1 < pInt->pCurFrame->ulNumSegments) { |
793 | /* Copy the data into the frame data buffer */ |
794 | memcpy(pInt->pCurFrame->pData + pFrameHdr->ulPartialFrameOffset, |
795 | *ppBuf, |
796 | pFrameHdr->ulPartialFrameSize); |
797 | /* The segment indices in the frame header are 1-based */ |
798 | i = pFrameHdr->ulPacketNum - 1; |
799 | /* Update the segment information */ |
800 | pInt->pCurFrame->pSegment[i].bIsValid = TRUE; |
801 | pInt->pCurFrame->pSegment[i].ulOffset = pFrameHdr->ulPartialFrameOffset; |
802 | /* |
803 | * Set the offset for the segment after this one and all other |
804 | * segments until we find a valid one or we run out of segments. |
805 | * This allows a codec to know where missing data would go for |
806 | * single loss. For multiple loss in a row the offset is set |
807 | * to the same offset since the size of the missing segments |
808 | * isn't known. |
809 | */ |
810 | for (i = pFrameHdr->ulPacketNum; |
811 | i < pInt->pCurFrame->ulNumSegments && |
812 | !pInt->pCurFrame->pSegment[i].bIsValid; |
813 | i++) { |
814 | pInt->pCurFrame->pSegment[i].ulOffset = ulOffset; |
815 | } |
816 | /* Check to see if all segments are present */ |
817 | bAllThere = TRUE; |
818 | for (i = 0; i < pInt->pCurFrame->ulNumSegments && bAllThere; i++) { |
819 | bAllThere = pInt->pCurFrame->pSegment[i].bIsValid; |
820 | } |
821 | /* Clear the return value */ |
822 | retVal = HXR_OK; |
823 | /* Are all segments present? */ |
824 | if (bAllThere) { |
825 | /* We've got the entire packet, so send it */ |
826 | retVal = rv_depacki_send_current_frame(pInt); |
827 | } |
828 | if (retVal == HXR_OK) { |
829 | /* Advance the buffer */ |
830 | *ppBuf += pFrameHdr->ulPartialFrameSize; |
831 | *pulLen -= pFrameHdr->ulPartialFrameSize; |
832 | } |
833 | } |
834 | } |
835 | } |
836 | |
837 | return retVal; |
838 | } |
839 | |
840 | HX_RESULT rv_depacki_handle_one_frame(rv_depack_internal* pInt, |
841 | BYTE** ppBuf, |
842 | UINT32* pulLen, |
843 | rm_packet* pPacket, |
844 | rv_frame_hdr* pFrameHdr) |
845 | { |
846 | HX_RESULT retVal = HXR_FAIL; |
847 | |
848 | if (pInt && ppBuf && pulLen && pPacket && pFrameHdr && *ppBuf) { |
849 | /* If we have a current frame, send it */ |
850 | retVal = rv_depacki_send_current_frame(pInt); |
851 | if (retVal == HXR_OK) { |
852 | /* Create a current frame */ |
853 | retVal = rv_depacki_create_frame(pInt, pPacket, pFrameHdr, |
854 | &pInt->pCurFrame); |
855 | if (retVal == HXR_OK) { |
856 | /* Set the return value */ |
857 | retVal = HXR_FAIL; |
858 | /* Sanity check on parsed values */ |
859 | if (*pulLen >= pInt->pCurFrame->ulDataLen) { |
860 | /* Copy the data */ |
861 | memcpy(pInt->pCurFrame->pData, *ppBuf, |
862 | pInt->pCurFrame->ulDataLen); |
863 | /* Set the one and only segment */ |
864 | pInt->pCurFrame->pSegment[0].bIsValid = TRUE; |
865 | pInt->pCurFrame->pSegment[0].ulOffset = 0; |
866 | /* Send the frame we just created */ |
867 | retVal = rv_depacki_send_current_frame(pInt); |
868 | if (retVal == HXR_OK) { |
869 | /* Advance the buffer */ |
870 | *ppBuf += pFrameHdr->ulFrameSize; |
871 | *pulLen -= pFrameHdr->ulFrameSize; |
872 | } |
873 | } |
874 | } |
875 | } |
876 | } |
877 | |
878 | return retVal; |
879 | } |
880 | |
881 | HX_RESULT rv_depacki_send_current_frame(rv_depack_internal* pInt) |
882 | { |
883 | HX_RESULT retVal = HXR_FAIL; |
884 | |
885 | if (pInt && pInt->fpAvail) { |
886 | /* Init local variables */ |
887 | HXBOOL bDoSend = TRUE; |
888 | UINT32 i = 0; |
889 | /* Clear the return value */ |
890 | retVal = HXR_OK; |
891 | /* Do we have a current frame? Not an error if we don't. */ |
892 | if (pInt->pCurFrame) { |
893 | /* Was the packet broken up by us? */ |
894 | if (pInt->bBrokenUpByUs) { |
895 | /* |
896 | * Make sure all the segments are there; |
897 | * otherwise, don't send it. After leaving |
898 | * the for loop below, bDoSend will only |
899 | * be TRUE if all the segments are valid. |
900 | */ |
901 | for (i = 0; i < pInt->pCurFrame->ulNumSegments && bDoSend; i++) { |
902 | bDoSend = pInt->pCurFrame->pSegment[i].bIsValid; |
903 | } |
904 | /* Are we going to send this frame? */ |
905 | if (bDoSend && pInt->pCurFrame->ulNumSegments) { |
906 | /* Collapse all the segment info into 1 segment */ |
907 | pInt->pCurFrame->pSegment[0].bIsValid = TRUE; |
908 | pInt->pCurFrame->pSegment[0].ulOffset = 0; |
909 | /* Reset the number of segments to 1 */ |
910 | pInt->pCurFrame->ulNumSegments = 1; |
911 | } |
912 | } |
913 | /* Are we going to send this frame? */ |
914 | if (bDoSend) { |
915 | /* Call the frame available function pointer */ |
916 | retVal = pInt->fpAvail(pInt->pAvail, |
917 | pInt->ulActiveSubStream, |
918 | pInt->pCurFrame); |
919 | |
920 | } else { |
921 | /* Free the frame */ |
922 | rv_depacki_cleanup_frame(pInt, &pInt->pCurFrame); |
923 | } |
924 | /* NULL out the pointer */ |
925 | pInt->pCurFrame = HXNULL; |
926 | } |
927 | } |
928 | |
929 | return retVal; |
930 | } |
931 | |
932 | void rv_depacki_cleanup_frame(rv_depack_internal* pInt, |
933 | rv_frame** ppFrame) |
934 | { |
935 | if (pInt && ppFrame && *ppFrame) { |
936 | /* Free the encoded frame buffer */ |
937 | if ((*ppFrame)->pData) { |
938 | rv_depacki_free(pInt, (*ppFrame)->pData); |
939 | (*ppFrame)->pData = HXNULL; |
940 | } |
941 | /* Free the segment array */ |
942 | if ((*ppFrame)->pSegment) { |
943 | rv_depacki_free(pInt, (*ppFrame)->pSegment); |
944 | (*ppFrame)->pSegment = HXNULL; |
945 | } |
946 | /* NULL out the frame */ |
947 | memset(*ppFrame, 0, sizeof(rv_frame)); |
948 | /* Delete the space for the frame struct itself */ |
949 | rv_depacki_free(pInt, *ppFrame); |
950 | /* NULL out the pointer */ |
951 | *ppFrame = HXNULL; |
952 | } |
953 | } |
954 | |
955 | HX_RESULT rv_depacki_create_frame(rv_depack_internal* pInt, |
956 | rm_packet* pPacket, |
957 | rv_frame_hdr* pFrameHdr, |
958 | rv_frame** ppFrame) |
959 | { |
960 | HX_RESULT retVal = HXR_FAIL; |
961 | |
962 | if (pInt && pPacket && pFrameHdr && ppFrame && |
963 | pFrameHdr->ulFrameSize && pFrameHdr->ulNumPackets) { |
964 | /* Init local variables */ |
965 | rv_frame* pFrame = HXNULL; |
966 | UINT32 ulSize = 0; |
967 | UINT32 ulSeqNum = 0; |
968 | UINT32 ulFlags = 0; |
969 | /* Clean out any existing frame */ |
970 | rv_depacki_cleanup_frame(pInt, ppFrame); |
971 | /* Allocate space rv_frame struct */ |
972 | pFrame = rv_depacki_malloc(pInt, sizeof(rv_frame)); |
973 | if (pFrame) { |
974 | /* NULL out the memory */ |
975 | memset(pFrame, 0, sizeof(rv_frame)); |
976 | /* Allocate enough space for the data */ |
977 | pFrame->pData = rv_depacki_malloc(pInt, pFrameHdr->ulFrameSize); |
978 | if (pFrame->pData) { |
979 | /* NULL out the memory */ |
980 | memset(pFrame->pData, 0, pFrameHdr->ulFrameSize); |
981 | /* Assign the data size */ |
982 | pFrame->ulDataLen = pFrameHdr->ulFrameSize; |
983 | /* Allocate space for segment array */ |
984 | ulSize = pFrameHdr->ulNumPackets * sizeof(rv_segment); |
985 | pFrame->pSegment = rv_depacki_malloc(pInt, ulSize); |
986 | if (pFrame->pSegment) { |
987 | /* |
988 | * NULL out the memory. This effectively sets |
989 | * all the bIsValid flags to FALSE and ulOffset |
990 | * values to zero. |
991 | */ |
992 | memset(pFrame->pSegment, 0, ulSize); |
993 | /* Assign the rest of the members of the frame struct */ |
994 | pFrame->ulNumSegments = pFrameHdr->ulNumPackets; |
995 | pFrame->ulTimestamp = pFrameHdr->ulTimestamp; |
996 | pFrame->bLastPacket = FALSE; |
997 | /* Look up the flags from the packet ASM rule */ |
998 | ulFlags = rv_depacki_rule_to_flags(pInt, pPacket->ucASMRule); |
999 | /* |
1000 | * If this is a packet with only multiple frames and the |
1001 | * packet is a keyframe packet, then we only want the FIRST frame |
1002 | * to be labelled as a keyframe. If this packet has a |
1003 | * last-partial frame followed by multiple frames, then |
1004 | * we don't want ANY of the multiple frames to be labelled |
1005 | * as a keyframe. To implement this logic, we can do |
1006 | * the following check: if this is a multiple frames header |
1007 | * AND that header did not start at the beginning of the packet, |
1008 | * then we need to clear the keyframe flag. |
1009 | */ |
1010 | if (pFrameHdr->eType == RVFrameTypeMultiple && |
1011 | pFrameHdr->ulHeaderOffset) { |
1012 | ulFlags &= ~HX_KEYFRAME_FLAG; |
1013 | } |
1014 | /* Assign the frame flags */ |
1015 | pFrame->usFlags = (UINT16) ulFlags; |
1016 | /* Compute the output sequence number */ |
1017 | if (pInt->bCreatedFirstFrame) { |
1018 | /* |
1019 | * The sequence number in the RV frame is only |
1020 | * one byte, so every 256 frames, it rolls over |
1021 | * from 255 back to 0. Check to see if we've |
1022 | * rolled over with this frame. |
1023 | */ |
1024 | if (pFrameHdr->ulSeqNum < pInt->ulLastSeqNumIn) { |
1025 | /* We rolled over */ |
1026 | pInt->ulLastSeqNumOut += pFrameHdr->ulSeqNum + 256 - pInt->ulLastSeqNumIn; |
1027 | } else { |
1028 | pInt->ulLastSeqNumOut += pFrameHdr->ulSeqNum - pInt->ulLastSeqNumIn; |
1029 | } |
1030 | /* Save the last input sequence number */ |
1031 | pInt->ulLastSeqNumIn = pFrameHdr->ulSeqNum; |
1032 | } else { |
1033 | /* |
1034 | * Always start the output sequence number at 0, even |
1035 | * if we lost a few packets and the actual input sequence |
1036 | * number in the RV frame my not be 0. |
1037 | */ |
1038 | pInt->ulLastSeqNumOut = 0; |
1039 | pInt->ulLastSeqNumIn = pFrameHdr->ulSeqNum; |
1040 | pInt->bCreatedFirstFrame = TRUE; |
1041 | } |
1042 | /* Assign the sequence number */ |
1043 | pFrame->usSequenceNum = (UINT16)(pInt->ulLastSeqNumOut & 0x0000FFFF); |
1044 | /* Assign the broken-up-by-us flag */ |
1045 | pInt->bBrokenUpByUs = pFrameHdr->bBrokenUpByUs; |
1046 | /* Assign the out parameter */ |
1047 | *ppFrame = pFrame; |
1048 | /* Clear the return value */ |
1049 | retVal = HXR_OK; |
1050 | } |
1051 | } |
1052 | } |
1053 | } |
1054 | |
1055 | return retVal; |
1056 | } |
1057 | |
1058 | HX_RESULT rv_depacki_seek(rv_depack_internal* pInt, UINT32 ulTime) |
1059 | { |
1060 | HX_RESULT retVal = HXR_FAIL; |
1061 | |
1062 | if (pInt) { |
1063 | /* Clean up any existing partial frame */ |
1064 | rv_depacki_cleanup_frame(pInt, &pInt->pCurFrame); |
1065 | /* Clear the return value */ |
1066 | retVal = HXR_OK; |
1067 | } |
1068 | |
1069 | return retVal; |
1070 | } |
1071 | |
1072 |