blob: 80c2c83b0f05ddd18c4923e45cfd22b6f69b8a0c
1 | /* ***** BEGIN LICENSE BLOCK ***** |
2 | * Source last modified: $Id: rm_parser.c,v 1.1.1.1.2.1 2005/05/04 18:21:36 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 <memory.h> |
40 | #include "../include/helix_types.h" |
41 | #include "../include/helix_result.h" |
42 | #include "../include/rm_parse.h" |
43 | #include "rm_parser_internal.h" |
44 | #include "../include/rm_memory_default.h" |
45 | #include "../include/rm_error_default.h" |
46 | #include "../include/rm_io_default.h" |
47 | #include "../include/memory_utils.h" |
48 | #include "../include/pack_utils.h" |
49 | |
50 | /* |
51 | * We will create a buffer of this size to handle |
52 | * reading of headers. The buffer will get increased |
53 | * in size if we encounter a header bigger than this |
54 | * size. Therefore, we would like to pick a reasonable |
55 | * size so that the we don't have lots of little |
56 | * allocations. This size should be the maximum |
57 | * of the expected size of the headers in the .rm file. |
58 | * |
59 | * XXXMEH - run lots of .rm files to see what a good |
60 | * size to pick. |
61 | */ |
62 | #define RM_PARSER_INITIAL_READ_BUFFER_SIZE 256 |
63 | |
64 | HXBOOL rm_parser_is_rm_file(BYTE* pBuf, UINT32 ulSize) |
65 | { |
66 | HXBOOL bRet = FALSE; |
67 | |
68 | /* Look for magic number ".RMF" at the beginning */ |
69 | if (ulSize >= 4) { |
70 | UINT32 ulID = rm_unpack32(&pBuf, &ulSize); |
71 | if (ulID == RM_HEADER_OBJECT) { |
72 | bRet = TRUE; |
73 | } |
74 | } |
75 | |
76 | return bRet; |
77 | } |
78 | |
79 | rm_parser* rm_parser_create(void* pError, |
80 | rm_error_func_ptr fpError) |
81 | { |
82 | return rm_parser_create2(pError, |
83 | fpError, |
84 | HXNULL, |
85 | rm_memory_default_malloc, |
86 | rm_memory_default_free); |
87 | } |
88 | |
89 | rm_parser* rm_parser_create2(void* pError, |
90 | rm_error_func_ptr fpError, |
91 | void* pMem, |
92 | rm_malloc_func_ptr fpMalloc, |
93 | rm_free_func_ptr fpFree) |
94 | { |
95 | rm_parser* pRet = HXNULL; |
96 | |
97 | if (fpMalloc) { |
98 | /* Allocate space for the rm_parser_internal struct |
99 | * by using the passed-in malloc function |
100 | */ |
101 | rm_parser_internal* pInt = (rm_parser_internal*) fpMalloc(pMem, sizeof(rm_parser_internal)); |
102 | if (pInt) { |
103 | /* Zero out the struct */ |
104 | memset((void*) pInt, 0, sizeof(rm_parser_internal)); |
105 | /* |
106 | * Assign the error members. If the user did not |
107 | * provide an error callback, then use the default |
108 | * rm_error_default(). |
109 | */ |
110 | if (fpError) { |
111 | pInt->fpError = fpError; |
112 | pInt->pUserError = pError; |
113 | } else { |
114 | pInt->fpError = rm_error_default; |
115 | pInt->pUserError = HXNULL; |
116 | } |
117 | /* Assign the memory functions */ |
118 | pInt->fpMalloc = fpMalloc; |
119 | pInt->fpFree = fpFree; |
120 | pInt->pUserMem = pMem; |
121 | /* Assign the return value */ |
122 | pRet = (rm_parser*) pInt; |
123 | } |
124 | } |
125 | |
126 | return pRet; |
127 | } |
128 | |
129 | HX_RESULT rm_parser_init_stdio(rm_parser* pParser, |
130 | FILE* fp) |
131 | { |
132 | HX_RESULT retVal = HXR_FAIL; |
133 | |
134 | if (pParser && fp) { |
135 | /* Get the internal parser struct */ |
136 | rm_parser_internal* pInt = (rm_parser_internal*) pParser; |
137 | /* Assign the default io functions */ |
138 | pInt->fpRead = rm_io_default_read; |
139 | pInt->fpSeek = rm_io_default_seek; |
140 | pInt->pUserRead = (void*) fp; |
141 | /* Clear the return value */ |
142 | retVal = HXR_OK; |
143 | } |
144 | |
145 | return retVal; |
146 | } |
147 | |
148 | HX_RESULT rm_parser_init_io(rm_parser* pParser, |
149 | void* pUserRead, |
150 | rm_read_func_ptr fpRead, |
151 | rm_seek_func_ptr fpSeek) |
152 | { |
153 | HX_RESULT retVal = HXR_FAIL; |
154 | |
155 | if (pParser && fpRead && fpSeek) { |
156 | /* Get the internal parser struct */ |
157 | rm_parser_internal* pInt = (rm_parser_internal*) pParser; |
158 | /* Assign the default io functions */ |
159 | pInt->fpRead = fpRead; |
160 | pInt->fpSeek = fpSeek; |
161 | pInt->pUserRead = pUserRead; |
162 | /* Clear the return value */ |
163 | retVal = HXR_OK; |
164 | } |
165 | |
166 | return retVal; |
167 | } |
168 | |
169 | HX_RESULT rm_parser_read_headers(rm_parser* pParser) |
170 | { |
171 | HX_RESULT retVal = HXR_FAIL; |
172 | |
173 | if (pParser) { |
174 | /* Get the internal parser struct */ |
175 | rm_parser_internal* pInt = (rm_parser_internal*) pParser; |
176 | /* Clear the return value */ |
177 | retVal = HXR_OK; |
178 | /* Allocate the read buffer if necessary */ |
179 | if (!pInt->pReadBuffer) { |
180 | retVal = rm_enforce_buffer_min_size(pInt->pUserMem, |
181 | pInt->fpMalloc, |
182 | pInt->fpFree, |
183 | &pInt->pReadBuffer, |
184 | &pInt->ulReadBufferSize, |
185 | RM_PARSER_INITIAL_READ_BUFFER_SIZE); |
186 | if (retVal == HXR_OK) { |
187 | /* Set the number of bytes read to zero */ |
188 | pInt->ulNumBytesRead = 0; |
189 | } |
190 | } |
191 | if (retVal == HXR_OK) { |
192 | retVal = rm_parseri_read_all_headers(pInt); |
193 | } |
194 | } |
195 | |
196 | return retVal; |
197 | } |
198 | |
199 | |
200 | UINT32 rm_parser_get_max_bit_rate(rm_parser* pParser) |
201 | { |
202 | UINT32 ulRet = 0; |
203 | |
204 | if (pParser) { |
205 | ulRet = ((rm_parser_internal*) pParser)->propHdr.max_bit_rate; |
206 | } |
207 | |
208 | return ulRet; |
209 | } |
210 | |
211 | UINT32 rm_parser_get_avg_bit_rate(rm_parser* pParser) |
212 | { |
213 | UINT32 ulRet = 0; |
214 | |
215 | if (pParser) { |
216 | ulRet = ((rm_parser_internal*) pParser)->propHdr.avg_bit_rate; |
217 | } |
218 | |
219 | return ulRet; |
220 | } |
221 | |
222 | UINT32 rm_parser_get_max_packet_size(rm_parser* pParser) |
223 | { |
224 | UINT32 ulRet = 0; |
225 | |
226 | if (pParser) { |
227 | ulRet = ((rm_parser_internal*) pParser)->propHdr.max_pkt_size; |
228 | } |
229 | |
230 | return ulRet; |
231 | } |
232 | |
233 | UINT32 rm_parser_get_avg_packet_size(rm_parser* pParser) |
234 | { |
235 | UINT32 ulRet = 0; |
236 | |
237 | if (pParser) { |
238 | ulRet = ((rm_parser_internal*) pParser)->propHdr.avg_pkt_size; |
239 | } |
240 | |
241 | return ulRet; |
242 | } |
243 | |
244 | UINT32 rm_parser_get_num_packets(rm_parser* pParser) |
245 | { |
246 | UINT32 ulRet = 0; |
247 | |
248 | if (pParser) { |
249 | ulRet = ((rm_parser_internal*) pParser)->propHdr.num_pkts; |
250 | } |
251 | |
252 | return ulRet; |
253 | } |
254 | |
255 | UINT32 rm_parser_get_duration(rm_parser* pParser) |
256 | { |
257 | UINT32 ulRet = 0; |
258 | |
259 | if (pParser) { |
260 | ulRet = ((rm_parser_internal*) pParser)->propHdr.duration; |
261 | } |
262 | |
263 | return ulRet; |
264 | } |
265 | |
266 | UINT32 rm_parser_get_preroll(rm_parser* pParser) |
267 | { |
268 | UINT32 ulRet = 0; |
269 | |
270 | if (pParser) { |
271 | ulRet = ((rm_parser_internal*) pParser)->propHdr.preroll; |
272 | } |
273 | |
274 | return ulRet; |
275 | } |
276 | |
277 | void rm_parser_set_index_offset(rm_parser* pParser, UINT32 offset) |
278 | { |
279 | UINT32 ulRet = 0; |
280 | |
281 | if (pParser) { |
282 | ((rm_parser_internal*) pParser)->propHdr.index_offset = offset; |
283 | } |
284 | } |
285 | |
286 | UINT32 rm_parser_get_index_offset(rm_parser* pParser) |
287 | { |
288 | UINT32 ulRet = 0; |
289 | |
290 | if (pParser) { |
291 | ulRet = ((rm_parser_internal*) pParser)->propHdr.index_offset; |
292 | } |
293 | |
294 | return ulRet; |
295 | } |
296 | |
297 | UINT32 rm_parser_get_data_offset(rm_parser* pParser) |
298 | { |
299 | UINT32 ulRet = 0; |
300 | |
301 | if (pParser) { |
302 | ulRet = ((rm_parser_internal*) pParser)->propHdr.data_offset; |
303 | } |
304 | |
305 | return ulRet; |
306 | } |
307 | |
308 | UINT32 rm_parser_get_data_size(rm_parser* pParser) |
309 | { |
310 | UINT32 ulRet = 0; |
311 | |
312 | if (pParser) { |
313 | ulRet = ((rm_parser_internal*) pParser)->pDataHdr[0].size; |
314 | } |
315 | |
316 | return ulRet; |
317 | } |
318 | |
319 | const char* rm_parser_get_title(rm_parser* pParser) |
320 | { |
321 | const char* pRet = HXNULL; |
322 | |
323 | if (pParser) { |
324 | pRet = (const char*)((rm_parser_internal*) pParser)->contHdr.title; |
325 | } |
326 | |
327 | return pRet; |
328 | } |
329 | |
330 | const char* rm_parser_get_author(rm_parser* pParser) |
331 | { |
332 | const char* pRet = HXNULL; |
333 | |
334 | if (pParser) { |
335 | pRet = (const char*)((rm_parser_internal*) pParser)->contHdr.author; |
336 | } |
337 | |
338 | return pRet; |
339 | } |
340 | |
341 | const char* rm_parser_get_copyright(rm_parser* pParser) |
342 | { |
343 | const char* pRet = HXNULL; |
344 | |
345 | if (pParser) { |
346 | pRet = (const char*)((rm_parser_internal*) pParser)->contHdr.copyright; |
347 | } |
348 | |
349 | return pRet; |
350 | } |
351 | |
352 | const char* rm_parser_get_comment(rm_parser* pParser) |
353 | { |
354 | const char* pRet = HXNULL; |
355 | |
356 | if (pParser) { |
357 | pRet = (const char*)((rm_parser_internal*) pParser)->contHdr.comment; |
358 | } |
359 | |
360 | return pRet; |
361 | } |
362 | |
363 | UINT32 rm_parser_get_num_streams(rm_parser* pParser) |
364 | { |
365 | UINT32 ulRet = 0; |
366 | |
367 | if (pParser) { |
368 | ulRet = ((rm_parser_internal*) pParser)->ulNumStreams; |
369 | } |
370 | |
371 | return ulRet; |
372 | } |
373 | |
374 | UINT32 rm_parser_get_stream_number(rm_parser* pParser, UINT32 ulStreamNum) |
375 | { |
376 | UINT32 ulRet = 0xffffffff; |
377 | |
378 | if (pParser) { |
379 | ulRet = rm_parseri_get_stream_number((rm_parser_internal*) pParser, ulStreamNum); |
380 | } |
381 | return ulRet; |
382 | } |
383 | |
384 | void rm_parser_set_stream_size(rm_parser* pParser, UINT32 ulStreamSize) |
385 | { |
386 | if (pParser) { |
387 | rm_parseri_set_stream_size((rm_parser_internal*) pParser, ulStreamSize); |
388 | } |
389 | } |
390 | |
391 | HX_RESULT rm_parser_get_file_properties(rm_parser* pParser, |
392 | rm_property** ppProp, |
393 | UINT32* pulNumProps) |
394 | { |
395 | HX_RESULT retVal = HXR_FAIL; |
396 | |
397 | if (pParser && ppProp && pulNumProps) { |
398 | /* Get the internal parser struct */ |
399 | rm_parser_internal* pInt = (rm_parser_internal*) pParser; |
400 | if (pInt->fpMalloc && pInt->fpFree) { |
401 | /* Get the number of file properties */ |
402 | UINT32 ulNum = rm_parseri_get_num_file_properties(pInt); |
403 | if (ulNum) { |
404 | /* Compute the size of the rm_property array */ |
405 | UINT32 ulSize = ulNum * sizeof(rm_property); |
406 | /* Allocate an array of this size */ |
407 | rm_property* pPropArr = pInt->fpMalloc(pInt->pUserMem, ulSize); |
408 | if (pPropArr) { |
409 | /* NULL out the memory */ |
410 | memset(pPropArr, 0, ulSize); |
411 | /* Collect the properties */ |
412 | retVal = rm_parseri_get_file_properties(pInt, pPropArr, ulNum); |
413 | if (retVal == HXR_OK) { |
414 | /* Assign the out parameters */ |
415 | *ppProp = pPropArr; |
416 | *pulNumProps = ulNum; |
417 | } else { |
418 | /* Free the array */ |
419 | pInt->fpFree(pInt->pUserMem, pPropArr); |
420 | } |
421 | } |
422 | } |
423 | } |
424 | } |
425 | |
426 | return retVal; |
427 | } |
428 | |
429 | void rm_parser_destroy_properties(rm_parser* pParser, |
430 | rm_property** ppProp, |
431 | UINT32* pulNumProps) |
432 | { |
433 | if (pParser && ppProp && pulNumProps && *ppProp && *pulNumProps) { |
434 | /* Get the internal parser struct */ |
435 | rm_parser_internal* pInt = (rm_parser_internal*) pParser; |
436 | if (pInt->fpFree) { |
437 | /* Get the pointer to the array */ |
438 | rm_property* pProp = *ppProp; |
439 | /* Clean up the properties */ |
440 | UINT32 i = 0; |
441 | for (i = 0; i < *pulNumProps; i++) { |
442 | rm_parseri_cleanup_rm_property(pInt, &pProp[i]); |
443 | } |
444 | /* Free the memory */ |
445 | pInt->fpFree(pInt->pUserMem, pProp); |
446 | /* NULL out the pointer */ |
447 | *ppProp = HXNULL; |
448 | /* Zero out the number of properties */ |
449 | *pulNumProps = 0; |
450 | } |
451 | } |
452 | } |
453 | |
454 | HX_RESULT rm_parser_get_stream_header(rm_parser* pParser, |
455 | UINT32 ulStreamNum, |
456 | rm_stream_header** ppHdr) |
457 | { |
458 | HX_RESULT retVal = HXR_FAIL; |
459 | |
460 | if (pParser && ppHdr) { |
461 | /* Get the internal parser struct */ |
462 | rm_parser_internal* pInt = (rm_parser_internal*) pParser; |
463 | if (pInt->fpMalloc) { |
464 | rm_stream_header* pHdr = (rm_stream_header*) pInt->fpMalloc(pInt->pUserMem, |
465 | sizeof(rm_stream_header)); |
466 | if (pHdr) { |
467 | /* NULL out the memory */ |
468 | memset(pHdr, 0, sizeof(rm_stream_header)); |
469 | /* Copy the stream header */ |
470 | retVal = rm_parseri_copy_stream_header(pInt, ulStreamNum, pHdr); |
471 | if (retVal == HXR_OK) { |
472 | /* Assign the out parameter */ |
473 | *ppHdr = pHdr; |
474 | } else { |
475 | /* Clean up the stream header */ |
476 | rm_parseri_cleanup_stream_header(pInt, pHdr); |
477 | /* Free the memory we allocated */ |
478 | pInt->fpFree(pInt->pUserMem, pHdr); |
479 | } |
480 | } |
481 | } |
482 | } |
483 | |
484 | return retVal; |
485 | } |
486 | |
487 | void rm_parser_destroy_stream_header(rm_parser* pParser, |
488 | rm_stream_header** ppHdr) |
489 | { |
490 | if (pParser && ppHdr && *ppHdr) { |
491 | /* Get the internal parser struct */ |
492 | rm_parser_internal* pInt = (rm_parser_internal*) pParser; |
493 | /* Cleanup the stream header */ |
494 | rm_parseri_cleanup_stream_header(pInt, *ppHdr); |
495 | /* Free the memory associated with this header */ |
496 | pInt->fpFree(pInt->pUserMem, *ppHdr); |
497 | /* NULL out the pointer */ |
498 | *ppHdr = HXNULL; |
499 | } |
500 | } |
501 | |
502 | HX_RESULT rm_parser_get_packet(rm_parser* pParser, |
503 | rm_packet** ppPacket) |
504 | { |
505 | HX_RESULT retVal = HXR_FAIL; |
506 | |
507 | if (pParser && ppPacket) { |
508 | /* Get the internal parser struct */ |
509 | rm_parser_internal* pInt = (rm_parser_internal*) pParser; |
510 | /* Read the next packet */ |
511 | retVal = rm_parseri_read_next_packet(pInt, ppPacket); |
512 | } |
513 | |
514 | return retVal; |
515 | } |
516 | |
517 | void rm_parser_destroy_packet(rm_parser* pParser, |
518 | rm_packet** ppPacket) |
519 | { |
520 | if (pParser && ppPacket && *ppPacket) { |
521 | /* Get the internal parser struct */ |
522 | rm_parser_internal* pInt = (rm_parser_internal*) pParser; |
523 | if (pInt->fpFree) { |
524 | /* Free the packet data */ |
525 | if ((*ppPacket)->pData) { |
526 | pInt->fpFree(pInt->pUserMem, (*ppPacket)->pData); |
527 | (*ppPacket)->pData = HXNULL; |
528 | } |
529 | /* Free the packet */ |
530 | pInt->fpFree(pInt->pUserMem, *ppPacket); |
531 | *ppPacket = HXNULL; |
532 | } |
533 | } |
534 | } |
535 | |
536 | HX_RESULT rm_parser_seek(rm_parser* pParser, |
537 | UINT32 ulTime) |
538 | { |
539 | HX_RESULT retVal = HXR_FAIL; |
540 | |
541 | if (pParser) { |
542 | /* Get the internal parser struct */ |
543 | rm_parser_internal* pInt = (rm_parser_internal*) pParser; |
544 | /* Read the next packet */ |
545 | retVal = rm_parseri_seek(pInt, ulTime); |
546 | } |
547 | |
548 | return retVal; |
549 | } |
550 | |
551 | HX_RESULT rm_parser_build_seek_table(rm_parser* pParser) |
552 | { |
553 | HX_RESULT retVal = HXR_FAIL; |
554 | |
555 | if (pParser) { |
556 | /* Get the internal parser struct */ |
557 | rm_parser_internal* pInt = (rm_parser_internal*) pParser; |
558 | /* Read the next packet */ |
559 | retVal = rm_parseri_build_seek_table(pInt); |
560 | } |
561 | |
562 | return retVal; |
563 | } |
564 | |
565 | HX_RESULT rm_parser_seek_in_seek_table(rm_parser* pParser, INT32 lStreamNumber, UINT32 ulSeekTime, INT32 lDirection, UINT32* pulFoundTime, UINT32* pulDataOffset, UINT32* pulIndex) |
566 | { |
567 | HX_RESULT retVal = HXR_FAIL; |
568 | |
569 | if (pParser) { |
570 | /* Get the internal parser struct */ |
571 | rm_parser_internal* pInt = (rm_parser_internal*) pParser; |
572 | /* Read the next packet */ |
573 | retVal = rm_parseri_search_seek_tables(pInt, lStreamNumber, ulSeekTime, lDirection, pulFoundTime, pulDataOffset, pulIndex); |
574 | } |
575 | |
576 | return retVal; |
577 | } |
578 | |
579 | void rm_parser_file_seek(rm_parser* pParser, UINT32 ulOffset) |
580 | { |
581 | HX_RESULT retVal = HXR_FAIL; |
582 | |
583 | if (pParser) { |
584 | /* Get the internal parser struct */ |
585 | rm_parser_internal* pInt = (rm_parser_internal*) pParser; |
586 | /* Read the next packet */ |
587 | rm_parseri_file_seek(pInt, ulOffset, HX_SEEK_ORIGIN_SET); |
588 | } |
589 | } |
590 | |
591 | void rm_parser_file_skip(rm_parser* pParser, UINT32 ulOffset) |
592 | { |
593 | HX_RESULT retVal = HXR_FAIL; |
594 | |
595 | if (pParser) { |
596 | /* Get the internal parser struct */ |
597 | rm_parser_internal* pInt = (rm_parser_internal*) pParser; |
598 | /* Read the next packet */ |
599 | rm_parseri_file_seek(pInt, ulOffset, HX_SEEK_ORIGIN_CUR); |
600 | } |
601 | } |
602 | |
603 | void rm_parser_destroy(rm_parser** ppParser) |
604 | { |
605 | if (ppParser) { |
606 | /* Get the internal parser struct */ |
607 | rm_parser_internal* pInt = (rm_parser_internal*) * ppParser; |
608 | if (pInt && pInt->fpFree) { |
609 | /* Save a pointer to fpFree and pUserMem */ |
610 | rm_free_func_ptr fpFree = pInt->fpFree; |
611 | void* pUserMem = pInt->pUserMem; |
612 | /* Clean up the content header */ |
613 | rm_parseri_cleanup_content_hdr(pInt); |
614 | /* Clean up the media props headers */ |
615 | rm_parseri_cleanup_all_media_props_hdrs(pInt); |
616 | /* Clean up all logical stream headers */ |
617 | rm_parseri_cleanup_all_logical_stream_hdrs(pInt); |
618 | /* Clean up the logical fileinfo header */ |
619 | rm_parseri_cleanup_logical_fileinfo_hdr(pInt); |
620 | //rm_parseri_cleanup_logical_stream_hdr(pInt, pInt->pLogicalFileInfo); |
621 | /* Clean up the read buffer */ |
622 | rm_parseri_cleanup_read_buffer(pInt); |
623 | /* Free the stream num map */ |
624 | rm_parseri_cleanup_stream_num_map(pInt); |
625 | /* Clean up the stream info array */ |
626 | rm_parseri_cleanup_stream_info_array(pInt); |
627 | /* Clean up the stream header array */ |
628 | rm_parseri_cleanup_all_stream_headers(pInt); |
629 | /* Clean up the data header */ |
630 | rm_parseri_cleanup_all_data_headers(pInt); |
631 | /* Null everything out */ |
632 | memset(pInt, 0, sizeof(rm_parser_internal)); |
633 | /* Free the rm_parser_internal struct memory */ |
634 | fpFree(pUserMem, pInt); |
635 | /* NULL out the pointer */ |
636 | *ppParser = HXNULL; |
637 | } |
638 | } |
639 | } |
640 | |
641 | void rm_parser_set_stream(rm_parser** ppParser, UINT32 ulStreamNum) |
642 | { |
643 | if (ppParser) { |
644 | /* Get the internal parser struct */ |
645 | rm_parser_internal* pInt = (rm_parser_internal*) * ppParser; |
646 | pInt->ulCurrentStream = ulStreamNum; |
647 | rm_parseri_file_seek(pInt, pInt->pMediaPropsHdr[pInt->ulCurrentStream].start_offset, HX_SEEK_ORIGIN_SET); |
648 | } |
649 | } |