summaryrefslogtreecommitdiff
path: root/audio_codec/libraac/rm_parser.c (plain)
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
64HXBOOL 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
79rm_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
89rm_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
129HX_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
148HX_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
169HX_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
200UINT32 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
211UINT32 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
222UINT32 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
233UINT32 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
244UINT32 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
255UINT32 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
266UINT32 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
277void 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
286UINT32 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
297UINT32 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
308UINT32 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
319const 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
330const 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
341const 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
352const 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
363UINT32 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
374UINT32 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
384void 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
391HX_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
429void 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
454HX_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
487void 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
502HX_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
517void 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
536HX_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
551HX_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
565HX_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
579void 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
591void 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
603void 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
641void 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}