summaryrefslogtreecommitdiff
path: root/audio_codec/libcook/rv_depack_internal.c (plain)
blob: 951d7db68d54b58d47025fa2c533cde38f110e0b
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 "helix_types.h"
43#include "helix_result.h"
44#include "pack_utils.h"
45#include "string_utils.h"
46#include "memory_utils.h"
47#include "packet_defines.h"
48#include "codec_defines.h"
49#include "stream_hdr_structs.h"
50#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
57void* 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
68void rv_depacki_free(rv_depack_internal* pInt, void* pMem)
69{
70 if (pInt && pInt->fpFree) {
71 pInt->fpFree(pInt->pUserMem, pMem);
72 }
73}
74
75HX_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
134HX_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
152HX_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
169HX_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
242void 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
252void 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
266HX_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
313HX_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
399HX_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
433HX_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
474UINT32 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
487UINT32 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
500HX_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
710HX_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
754HX_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
840HX_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
881HX_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
932void 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
955HX_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
1058HX_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