2009-12-07 Rolf Bjarne Kvinge <RKvinge@novell.com>
[moon.git] / src / asf / asf-structures.cpp
blob15d281b51f3e2d20d0c7fa515e059dd9835870ad
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3 * asf.cpp:
5 * Contact:
6 * Moonlight List (moonlight-list@lists.ximian.com)
8 * Copyright 2007 Novell, Inc. (http://www.novell.com)
10 * See the LICENSE file included with the distribution for details.
13 #ifdef HAVE_CONFIG_H
14 #include <config.h>
15 #endif
17 #include "asf.h"
19 char*
20 wchar_to_utf8 (void* unicode, guint32 length)
22 char* result = NULL;
24 if (length <= 0)
25 return NULL;
27 GError* err = NULL;
28 result = g_utf16_to_utf8 ((const gunichar2*) unicode, length, NULL, NULL, &err);
29 if (result == NULL) {
30 ASF_LOG ("Could not convert to utf8from utf16: %s\n", err->message);
31 g_error_free (err);
32 err = NULL;
35 return result;
38 bool
39 asf_header_validate (const asf_header* header, ASFParser* parser)
41 // SPEC: This field shall be set to ASF_Header_Object
42 if (!asf_guid_validate (&header->id, &asf_guids_header, parser)) {
43 return false;
46 // SPEC: valid values are at least 30 bytes
47 if (header->size < 30) {
48 parser->AddError (g_strdup_printf ("Invalid size (expected >= 30, got %" G_GUINT64_FORMAT ").", header->size));
49 return false;
52 // SPEC: This field must be set to the value 0x02. If the this value is different when read, the application should fail to source the content.
53 if (header->reserved2 != 0x02) {
54 parser->AddError (g_strdup_printf ("Invalid reserved2 value (expected 0x02, got: %x).", header->reserved2));
55 return false;
58 return true;
61 bool
62 asf_file_properties_validate (const asf_file_properties* obj, ASFParser* parser)
64 // SPEC: This field shall be set to ASF_File_Properties_Object
65 if (!asf_guid_validate (&obj->id, &asf_guids_file_properties, parser)) {
66 return false;
69 // SPEC: Valid values are at least 104 bytes
70 if (obj->size < 104) {
71 parser->AddError (g_strdup_printf ("Invalid size (expected >= 104, got %" G_GUINT64_FORMAT ").", obj->size));
72 return false;
75 // SPEC: the values for the Minimum Data Packet Size and Maximum Data Packet Size
76 // fields shall be set to the same value, and this value should be set to the packet size,
77 // even when the Broadcast Flag in the Flags field is set to 1.
78 if (obj->min_packet_size != obj->max_packet_size) {
79 // This is not logical at all, but it's what the spec says.
80 // besides, our code depends on it (it makes a few minor things easier).
81 parser->AddError (g_strdup_printf ("The min packet size (%d) is different from the max packet size (%d).", obj->min_packet_size, obj->max_packet_size));
82 return false;
85 if (obj->size > parser->header->size) {
86 parser->AddError (g_strdup_printf ("The size of the file property object (%" G_GUINT64_FORMAT ") is bigger than the sizeof the entire header itself (%" G_GUINT64_FORMAT ").", obj->size, parser->header->size));
87 return false;
90 return true;
93 bool
94 asf_stream_properties_validate (const asf_stream_properties* obj, ASFParser* parser)
96 if (!(asf_guid_validate (&obj->id, &asf_guids_stream_properties, parser))) {
97 return false;
100 if (obj->size < 78) {
101 parser->AddError (g_strdup_printf ("Invalid size (expected >= 78, got %" G_GUINT64_FORMAT ").", obj->size));
102 return false;
105 return true;
108 bool
109 asf_header_extension_validate (const asf_header_extension* obj, ASFParser* parser)
111 if (!(asf_guid_validate (&obj->id, &asf_guids_header_extension, parser))) {
112 return false;
115 if (obj->size < 46) {
116 parser->AddError (g_strdup_printf ("Invalid size (expected >= 46, got %" G_GUINT64_FORMAT ").", obj->size));
117 return false;
120 if (obj->data_size < 24 && obj->data_size > 1) {
121 parser->AddError (g_strdup_printf ("Invalid data_size (expected >= 24 or 0, got %u).", obj->data_size));
122 return false;
123 } else if (obj->data_size != 0 && obj->data_size + 46 != obj->size) {
124 parser->AddError (g_strdup_printf ("Invalid data_size (expected size - 46, got %" G_GUINT64_FORMAT " - 46 = %u).", obj->size, obj->data_size));
125 return false;
128 if (obj->data_size == 0)
129 return true;
131 guint64 max_size = obj->size;
132 guint64 size = 46;
133 guint64 length;
134 guint64 accum_length = 0;
135 void *data = obj->get_data ();
136 asf_object *header_obj;
138 do {
139 if (size + 24 /* minimum object size */ > max_size) {
140 parser->AddError (g_strdup_printf ("Invalid header extension size."));
141 return false;
144 header_obj = (asf_object *) (((char *) data) + accum_length);
145 length = header_obj->size;
146 if (length == 0) {
147 parser->AddError (g_strdup_printf ("Invalid header length is zero"));
148 return false;
150 accum_length += length;
151 size += length;
152 if (size > max_size) {
153 parser->AddError (g_strdup_printf ("Invalid header extension object."));
154 return false;
157 if (!asf_object_validate_exact (header_obj, parser))
158 return false;
160 } while (size < max_size);
162 return true;
165 bool asf_codec_list_validate (const asf_codec_list* obj, ASFParser* parser)
167 if (!(asf_guid_validate (&obj->id, &asf_guids_codec_list, parser))) {
168 return false;
171 if (obj->size < 44) {
172 parser->AddError (g_strdup_printf ("Invalid size (expected >= 44, got %" G_GUINT64_FORMAT ").", obj->size));
173 return false;
175 // TODO: More verifications?
176 return true;
179 bool asf_script_command_validate (const asf_script_command* obj, ASFParser* parser)
181 if (!(asf_guid_validate (&obj->id, &asf_guids_script_command, parser))) {
182 return false;
185 if (obj->size < 44) {
186 parser->AddError (g_strdup_printf ("Invalid size (expected >= 44, got %" G_GUINT64_FORMAT ").", obj->size));
187 return false;
189 // TODO: More verifications?
190 return true;
193 bool asf_marker_validate (const asf_marker* obj, ASFParser* parser)
195 if (!(asf_guid_validate (&obj->id, &asf_guids_marker, parser))) {
196 return false;
199 if (obj->size < 48) {
200 parser->AddError (g_strdup_printf ("Invalid size (expected >= 48, got %" G_GUINT64_FORMAT ").", obj->size));
201 return false;
203 // TODO: More verifications?
204 return true;
207 bool asf_bitrate_mutual_exclusion_validate (const asf_bitrate_mutual_exclusion* obj, ASFParser* parser)
209 if (!(asf_guid_validate (&obj->id, &asf_guids_bitrate_mutual_exclusion, parser))) {
210 return false;
213 if (obj->size < 42) {
214 parser->AddError (g_strdup_printf ("Invalid size (expected >= 42, got %" G_GUINT64_FORMAT ").", obj->size));
215 return false;
217 // TODO: More verifications?
218 return true;
221 bool asf_error_correction_validate (const asf_error_correction* obj, ASFParser* parser)
223 if (!(asf_guid_validate (&obj->id, &asf_guids_error_correction, parser))) {
224 return false;
227 if (obj->size < 44) {
228 parser->AddError (g_strdup_printf ("Invalid size (expected >= 44, got %" G_GUINT64_FORMAT ").", obj->size));
229 return false;
231 // TODO: More verifications?
232 return true;
235 bool asf_content_description_validate (const asf_content_description* obj, ASFParser* parser)
237 if (!(asf_guid_validate (&obj->id, &asf_guids_content_description, parser))) {
238 return false;
241 if (obj->size < 34) {
242 parser->AddError (g_strdup_printf ("Invalid size (expected >= 34, got %" G_GUINT64_FORMAT ").", obj->size));
243 return false;
245 // TODO: More verifications?
246 return true;
249 bool asf_extended_content_description_validate (const asf_extended_content_description* obj, ASFParser* parser)
251 if (!(asf_guid_validate (&obj->id, &asf_guids_extended_content_description, parser))) {
252 return false;
255 if (obj->size < 26) {
256 parser->AddError (g_strdup_printf ("Invalid size (expected >= 26, got %" G_GUINT64_FORMAT ").", obj->size));
257 return false;
259 // TODO: More verifications?
260 return true;
263 bool asf_stream_bitrate_properties_validate (const asf_stream_bitrate_properties* obj, ASFParser* parser)
265 if (!(asf_guid_validate (&obj->id, &asf_guids_stream_bitrate_properties, parser))) {
266 return false;
269 if (obj->size < 26) {
270 parser->AddError (g_strdup_printf ("Invalid size (expected >= 26, got %" G_GUINT64_FORMAT ").", obj->size));
271 return false;
273 // TODO: More verifications?
274 return true;
277 bool asf_data_validate (const asf_data* obj, ASFParser* parser)
279 if (!(asf_guid_validate (&obj->id, &asf_guids_data, parser))) {
280 return false;
283 if (obj->size < 50) {
284 parser->AddError (g_strdup_printf ("Invalid size (expected >= 50, got %" G_GUINT64_FORMAT ").", obj->size));
285 return false;
288 if (!(asf_guid_compare (&obj->file_id, &parser->GetFileProperties ()->file_id))) {
289 parser->AddError ("Data file id and header's file properties file id don't match.");
290 return false;
293 // TODO: More verifications?
294 return true;
297 MediaResult
298 asf_error_correction_data::FillInAll (ASFContext *context)
300 IMediaSource *source = context->source;
301 data = 0;
302 first = 0;
303 second = 0;
305 if (!source->ReadAll (&data, 1)) {
306 ASF_LOG_ERROR ("asf_error_correction_data::FillInAll (): Error while reading 'data'.\n");
307 return MEDIA_READ_ERROR;
310 if (!is_error_correction_present ())
311 return MEDIA_SUCCESS;
313 if (!source->ReadAll (&first, 1)) {
314 ASF_LOG_ERROR ("asf_error_correction_data::FillInAll (): Error while reading 'first'.\n");
315 return MEDIA_READ_ERROR;
318 if (!source->ReadAll (&second, 1)) {
319 ASF_LOG_ERROR ("asf_error_correction_data::FillInAll (): Error while reading 'second'.\n");
320 return MEDIA_READ_ERROR;
323 return MEDIA_SUCCESS;
326 void
327 asf_error_correction_data_dump (asf_error_correction_data* obj)
329 char* tostring = obj->tostring ();
330 ASF_DUMP ("ASF_ERROR_CORRECTION_DATA\n");
331 ASF_DUMP ("\tdata = 0x%X\n", (asf_dword) obj->data);
332 ASF_DUMP ("\tdata = 0b%s\n", tostring); g_free (tostring);
333 ASF_DUMP ("\t\tis_error_correction_present: %d\n", obj->is_error_correction_present ());
334 ASF_DUMP ("\t\tis_opaque_data_present: %d\n", obj->is_opaque_data_present ());
335 ASF_DUMP ("\t\tdata_length: %d\n", obj->get_data_length ());
336 ASF_DUMP ("\t\tlength_type: %d\n", obj->get_error_correction_length_type ());
337 ASF_DUMP ("\tfirst = %X\n", (asf_dword) obj->first);
339 ASF_DUMP ("\tsecond = %X\n", (asf_dword) obj->second);
342 MediaResult
343 asf_payload_parsing_information::FillInAll (ASFContext *context)
345 ASFParser *parser = context->parser;
346 IMediaSource *source = context->source;
347 // There's no guarantee that these fields will be written to by Read ()
349 packet_length = 0;
350 sequence = 0;
351 padding_length = 0;
352 send_time = 0;
353 duration = 0;
355 if (!source->ReadAll (&length_type_flags, 1)) {
356 ASF_LOG_ERROR ("asf_payload_parsing_information::FillInAll (): Error while reading 'length_type_flags'.\n");
357 return MEDIA_READ_ERROR;
360 if (!source->ReadAll (&property_flags, 1)) {
361 ASF_LOG_ERROR ("asf_payload_parsing_information::FillInAll (): Error while reading 'property_flags'.\n");
362 return MEDIA_READ_ERROR;
365 if (get_packet_length_type () == 0) {
366 packet_length = parser->GetPacketSize ();
367 } else {
368 if (!ASFParser::ReadEncoded (source, get_packet_length_type (), &packet_length)) {
369 ASF_LOG_ERROR ("asf_payload_parsing_information::FillInAll (): Error while reading 'packet_length'.\n");
370 return MEDIA_READ_ERROR;
374 if (!ASFParser::ReadEncoded (source, get_sequence_type (), &sequence)) {
375 ASF_LOG_ERROR ("asf_payload_parsing_information::FillInAll (): Error while reading 'sequence'.\n");
376 return MEDIA_READ_ERROR;
379 if (!ASFParser::ReadEncoded (source, get_padding_length_type (), &padding_length)) {
380 ASF_LOG_ERROR ("asf_payload_parsing_information::FillInAll (): Error while reading 'padding_length'.\n");
381 return MEDIA_READ_ERROR;
384 if (!source->ReadAll (&send_time, 4)) {
385 ASF_LOG_ERROR ("asf_payload_parsing_information::FillInAll (): Error while reading 'send_time'.\n");
386 return MEDIA_READ_ERROR;
389 if (!source->ReadAll (&duration, 2)) {
390 ASF_LOG_ERROR ("asf_payload_parsing_information::FillInAll (): Error while reading 'duration'.\n");
391 return MEDIA_READ_ERROR;
394 return MEDIA_SUCCESS;
397 void asf_payload_parsing_information_dump (asf_payload_parsing_information* obj)
399 ASF_DUMP ("ASF_PAYLOAD_PARSING_INFORMATION\n");
400 ASF_DUMP ("\tlength_type_flags = %X\n", (asf_dword) obj->length_type_flags);
401 ASF_DUMP ("\t\tmultiple_payloads_present = %d\n", obj->is_multiple_payloads_present ());
402 ASF_DUMP ("\t\tsequence_type = %d\n", obj->get_sequence_type ());
403 ASF_DUMP ("\t\tpadding_length_type = %d\n", obj->get_padding_length_type ());
404 ASF_DUMP ("\t\tpacket_length_type = %d\n", obj->get_packet_length_type ());
405 ASF_DUMP ("\tproperty_flags = %X\n", (asf_dword) obj->property_flags);
406 ASF_DUMP ("\t\treplicated_data_length_type = %d\n", obj->get_replicated_data_length_type ());
407 ASF_DUMP ("\t\toffset_into_media_object_length_type = %d\n", obj->get_offset_into_media_object_length_type ());
408 ASF_DUMP ("\t\tmedia_object_number_length_type = %d\n", obj->get_media_object_number_length_type ());
409 ASF_DUMP ("\t\tstream_number_length_type = %d\n", obj->get_stream_number_length_type ());
410 ASF_DUMP ("\tpacket_length = %u\n", (asf_dword) obj->packet_length);
411 ASF_DUMP ("\tsequence = %u\n", (asf_dword) obj->sequence);
412 ASF_DUMP ("\tpadding_length = %u\n", (asf_dword) obj->padding_length);
413 ASF_DUMP ("\tsend_time = %u\n", (asf_dword) obj->send_time);
414 ASF_DUMP ("\tduration = %u\n", (asf_dword) obj->duration);
417 asf_single_payload *
418 asf_single_payload::Clone ()
420 asf_single_payload *result = new asf_single_payload ();
422 result->stream_id = stream_id;
423 result->is_key_frame = is_key_frame;
424 result->media_object_number = media_object_number;
425 result->offset_into_media_object = offset_into_media_object;
426 result->replicated_data_length = replicated_data_length;
427 if (replicated_data != NULL) {
428 result->replicated_data = (asf_byte *) g_malloc (replicated_data_length);
429 memcpy (result->replicated_data, replicated_data, replicated_data_length);
431 result->payload_data_length = payload_data_length;
432 if (payload_data != NULL) {
433 result->payload_data = (asf_byte *) g_malloc (payload_data_length);
434 memcpy (result->payload_data, payload_data, payload_data_length);
436 result->presentation_time = presentation_time;
438 return result;
441 MediaResult
442 asf_single_payload::FillInAll (ASFContext *context, asf_error_correction_data* ecd, asf_payload_parsing_information ppi, asf_multiple_payloads* mp)
444 ASFParser *parser = context->parser;
445 IMediaSource *source = context->source;
447 if (!source->ReadAll (&stream_id, 1)) {
448 ASF_LOG_ERROR ("asf_single_payload::FillInAll (): Error while reading 'stream_id'.\n");
449 return MEDIA_READ_ERROR;
452 is_key_frame = stream_id & 0x80;
453 stream_id = stream_id & 0x7F;
455 if (!parser->IsValidStream (stream_id)) {
456 ASF_LOG_ERROR ("asf_single_payload::FillInAll: Invalid stream number (%d).", (int) stream_id);
457 return MEDIA_INVALID_DATA;
460 media_object_number = 0;
461 offset_into_media_object = 0;
462 replicated_data_length = 0;
463 replicated_data = NULL;
464 payload_data_length = 0;
465 payload_data = NULL;
466 presentation_time = 0;
468 ASF_LOG ("asf_single_payload::FillInAll (%p, %p, [Length type flags: %i, property flags: %i (mon:%i,oimo:%i,rpl:%i,sl:%i]). Stream: %i\n", context, ecd, ppi.length_type_flags, ppi.property_flags, ppi.get_offset_into_media_object_length_type (), ppi.get_media_object_number_length_type (), ppi.get_replicated_data_length_type (), ppi.get_stream_number_length_type (), stream_id);
470 if (!ASFParser::ReadEncoded (source, ppi.get_media_object_number_length_type (), &media_object_number)) {
471 ASF_LOG_ERROR ("asf_single_payload::FillInAll (): Error while reading 'media_object_number'.\n");
472 return MEDIA_READ_ERROR;
475 if (!ASFParser::ReadEncoded (source, ppi.get_offset_into_media_object_length_type (), &offset_into_media_object)) {
476 ASF_LOG_ERROR ("asf_single_payload::FillInAll (): Error while reading 'offset_into_media_object'.\n");
477 return MEDIA_READ_ERROR;
480 if (!ASFParser::ReadEncoded (source, ppi.get_replicated_data_length_type (), &replicated_data_length)) {
481 ASF_LOG_ERROR ("asf_single_payload::FillInAll (): Error while reading 'replicated_data_length'.\n");
482 return MEDIA_READ_ERROR;
485 if (replicated_data_length >= 2 && replicated_data_length < 7) {
486 parser->AddError (g_strdup_printf ("Invalid replicated data length: %d", replicated_data_length));
487 return MEDIA_INVALID_DATA;
490 if (replicated_data_length > parser->file_properties->max_packet_size) {
491 parser->AddError ("Data corruption in payload.");
492 return MEDIA_INVALID_DATA;
495 replicated_data = (asf_byte*) parser->MallocVerified (replicated_data_length);
496 if (replicated_data == NULL) {
497 return MEDIA_OUT_OF_MEMORY;
500 if (!source->ReadAll (replicated_data, replicated_data_length)) {
501 ASF_LOG_ERROR ("asf_single_payload::FillInAll (): Error while reading 'replicated_data'.\n");
502 return MEDIA_READ_ERROR;
505 if (replicated_data_length == 1) {
506 presentation_time = offset_into_media_object;
507 } else if (replicated_data_length >= 8) {
508 presentation_time = *(((asf_dword*) replicated_data) + 1);
511 if (mp != NULL) {
512 if (!ASFParser::ReadEncoded (source, mp->get_payload_length_type (), &payload_data_length)) {
513 ASF_LOG_ERROR ("asf_single_payload::FillInAll (): Error while reading 'payload_data_length'.\n");
514 return MEDIA_READ_ERROR;
517 if (payload_data_length == 0) {
518 parser->AddError ("Warning: Invalid payload data length: can't be 0.");
519 //return false;
521 } else {
522 int payload_length;
523 // The number of bytes in this array can be calculated from the overall Packet Length field,
524 // and is equal to the Packet Length
525 payload_length = ppi.packet_length;
526 // minus the packet header length,
527 payload_length -= ppi.get_struct_size ();
528 payload_length -= ecd->get_struct_size (),
529 // minus the payload header length (including Replicated Data),
530 payload_length -= 1; // stream_number
531 payload_length -= ASF_DECODE_PACKED_SIZE (ppi.get_media_object_number_length_type ());
532 payload_length -= ASF_DECODE_PACKED_SIZE (ppi.get_offset_into_media_object_length_type ());
533 payload_length -= ASF_DECODE_PACKED_SIZE (ppi.get_replicated_data_length_type ());
534 payload_length -= replicated_data_length;
535 // minus the Padding Length.
536 payload_length -= ppi.padding_length;
537 ASF_LOG ("payload_length: %d. packet_length: %d, ppi.get_struct_size: %d, replicated_data_length: %d, padding_length: %d, ecd.get_struct_size: %d\n",
538 payload_length, ppi.packet_length, ppi.get_struct_size (), replicated_data_length, ppi.padding_length, ecd->get_struct_size ());
540 if (payload_length < 0) {
541 parser->AddError (g_strdup_printf ("Invalid payload length: %d", payload_length));
542 return MEDIA_INVALID_DATA;
545 payload_data_length = (asf_dword) payload_length;
548 if (payload_data_length > 0) {
549 if (payload_data_length >= parser->file_properties->max_packet_size) {
550 parser->AddError ("Data corruption in payload.");
551 return MEDIA_INVALID_DATA;
554 payload_data = (asf_byte*) parser->MallocVerified (payload_data_length);
555 if (payload_data == NULL) {
556 return MEDIA_OUT_OF_MEMORY;
559 if (!source->ReadAll (payload_data, payload_data_length)) {
560 ASF_LOG_ERROR ("asf_single_payload::FillInAll (): Error while reading 'payload_data'.\n");
561 return MEDIA_READ_ERROR;
566 return MEDIA_SUCCESS;
569 asf_single_payload::~asf_single_payload ()
571 g_free (replicated_data);
572 replicated_data = NULL;
574 g_free (payload_data);
575 payload_data = NULL;
578 void
579 asf_single_payload_dump (asf_single_payload* obj)
581 ASF_DUMP ("ASF_SINGLE_PAYLOAD\n");
582 ASF_DUMP ("\tstream_number = %u\n", (asf_dword) obj->stream_id);
583 ASF_DUMP ("\tis_key_frame = %s\n", obj->is_key_frame ? "true" : "false");
584 ASF_DUMP ("\tmedia_object_number = %u\n", (asf_dword) obj->media_object_number);
585 ASF_DUMP ("\toffset_into_media_object = %u\n", (asf_dword) obj->offset_into_media_object);
586 ASF_DUMP ("\treplicated_data_length = %u\n", (asf_dword) obj->replicated_data_length);
587 ASF_DUMP ("\treplicated_data = %s\n", obj->replicated_data ? "non-null" : "null");
588 ASF_DUMP ("\tpayload_data_length = %u\n", (asf_dword) obj->payload_data_length);
589 ASF_DUMP ("\tpayload_data = %s\n", obj->payload_data ? "non-null" : "null");
590 ASF_DUMP ("\tget_presentation_time = %" G_GINT64_FORMAT "\n", obj->get_presentation_time ());
593 bool
594 asf_multiple_payloads::ResizeList (ASFParser* parser, int requested_size)
596 if (requested_size <= payloads_size)
597 return true;
599 asf_single_payload** new_list;
601 new_list = (asf_single_payload**) parser->MallocVerified ((requested_size + 1) * sizeof (asf_single_payload*));
603 if (new_list == NULL) {
604 return false;
607 if (payloads != NULL) {
608 memcpy (new_list, payloads, sizeof (asf_single_payload*) * payloads_size);
609 g_free (payloads);
612 payloads = new_list;
613 payloads_size = requested_size;
615 return true;
618 int
619 asf_multiple_payloads::CountCompressedPayloads (ASFParser* parser, asf_single_payload* payload)
621 asf_byte* data = payload->payload_data;
622 asf_dword length = payload->payload_data_length;
623 asf_byte size = 0;
624 guint32 offset = 0;
625 int counter = 0;
627 if (data == NULL) {
628 parser->AddError ("Compressed payload is corrupted.");
629 return false;
632 while (true) {
633 counter++;
634 size = *(data + offset);
635 offset += (size + 1);
636 if (offset > length || size == 0) {
637 parser->AddError ("Compressed payloads are corrupted.");
638 return false;
639 } else if (offset == length) {
640 break;
644 return counter;
647 MediaResult
648 asf_multiple_payloads::ReadCompressedPayload (ASFParser* parser, asf_single_payload* first, int count, int start_index)
650 asf_byte* data = first->payload_data;
651 asf_byte size = 0;
652 guint32 offset = 0;
653 asf_single_payload* payload = NULL;
655 for (int i = 0; i < count; i++) {
656 size = *(data + offset);
657 offset += 1;
659 payload = new asf_single_payload ();
660 payloads [start_index + i] = payload;
662 payload->stream_id = first->stream_id;
663 payload->is_key_frame = first->is_key_frame;
664 payload->media_object_number = first->media_object_number + i;
665 payload->offset_into_media_object = 0;
666 payload->replicated_data_length = 0;
667 payload->replicated_data = NULL;
668 payload->presentation_time = first->presentation_time + i * first->get_presentation_time_delta ();
669 payload->payload_data_length = size;
670 payload->payload_data = (asf_byte*) parser->Malloc (size);
671 if (payload->payload_data == NULL) {
672 return MEDIA_OUT_OF_MEMORY;
674 memcpy (payload->payload_data, data + offset, size);
675 offset += size;
678 return MEDIA_SUCCESS;
681 MediaResult
682 asf_multiple_payloads::FillInAll (ASFContext *context, asf_error_correction_data* ecd, asf_payload_parsing_information ppi)
684 ASFParser *parser = context->parser;
685 IMediaSource *source = context->source;
686 MediaResult result;
687 int count;
689 if (ppi.is_multiple_payloads_present ()) {
690 if (!source->ReadAll (&payload_flags, 1)) {
691 ASF_LOG_ERROR ("asf_multiple_payload::FillInAll (): Error while reading 'payload_flags'.\n");
692 return MEDIA_READ_ERROR;
695 count = payload_flags & 0x3F; // number of payloads is encoded in a byte, no need to check for extreme values.
697 if (count <= 0) {
698 parser->AddError (g_strdup_printf ("Invalid number of payloads: %d", count));
699 return MEDIA_INVALID_DATA;
702 if (!ResizeList (parser, count)) {
703 return MEDIA_OUT_OF_MEMORY;
706 ASF_LOG ("asf_multiple_payloads::FillInAll (): Reading %d payloads...\n", count);
708 int current_index = 0;
709 for (int i = 0; i < count; i++) {
710 payloads [current_index] = new asf_single_payload ();
712 result = payloads [current_index]->FillInAll (context, ecd, ppi, this);
713 if (!MEDIA_SUCCEEDED (result)) {
714 delete payloads [current_index];
715 payloads [current_index] = NULL;
716 return result;
719 if (payloads [current_index]->is_compressed ()) {
720 asf_single_payload* first = payloads [current_index];
721 int number = CountCompressedPayloads (parser, first);
722 if (number <= 0) {
723 return MEDIA_INVALID_DATA;
725 if (!ResizeList (parser, number + payloads_size)) {
726 return MEDIA_OUT_OF_MEMORY;
728 result = ReadCompressedPayload (parser, first, number, current_index);
729 if (!MEDIA_SUCCEEDED (result)) {
730 return result;
732 delete first;
735 ASF_DUMP ("-Payload #%d:\n", current_index + 1);
736 asf_single_payload_dump (payloads [current_index]);
738 current_index++;
740 } else {
741 ASF_LOG ("asf_multiple_payloads::FillInAll (%p, %p, ?): A single payload\n", context, ecd);
743 asf_single_payload* payload = new asf_single_payload ();
744 result = payload->FillInAll (context, ecd, ppi, NULL);
745 if (!MEDIA_SUCCEEDED (result)) {
746 delete payload;
747 return result;
750 if (payload->is_compressed ()) {
751 int counter = 0;
753 counter = CountCompressedPayloads (parser, payload);
754 if (counter <= 0) {
755 return MEDIA_INVALID_DATA;
758 if (!ResizeList (parser, counter)) {
759 return MEDIA_OUT_OF_MEMORY;
762 result = ReadCompressedPayload (parser, payload, counter, 0);
763 if (!MEDIA_SUCCEEDED (result)) {
764 return result;
767 delete payload;
769 } else {
770 payloads = (asf_single_payload**) parser->MallocVerified (sizeof (asf_single_payload*) * 2);
771 if (payloads == NULL) {
772 return MEDIA_OUT_OF_MEMORY;
774 payloads [0] = payload;
776 payload_flags = 1; // 1 payload
779 return MEDIA_SUCCESS;
782 void asf_multiple_payloads_dump (asf_multiple_payloads* obj)
784 ASF_DUMP ("ASF_MULTIPLE_PAYLOADS\n");
785 ASF_DUMP ("\tpayload_flags = %u\n", (asf_dword) obj->payload_flags);
786 ASF_DUMP ("\t\tnumber of payloads = %d\n", obj->get_number_of_payloads ());
787 ASF_DUMP ("\t\tpayload_length_type = %d\n", obj->get_payload_length_type ());
789 if (obj->payloads) {
790 int i = 0;
791 while (obj->payloads [i] != NULL) {
792 ASF_DUMP ("\tpayload #%d:\n", i + 1);
793 asf_single_payload_dump (obj->payloads [i++]);
795 } else {
796 ASF_DUMP ("\t<no payloads here>\n");
800 asf_script_command_entry**
801 asf_script_command::get_commands (ASFParser* parser, char*** command_types)
803 //printf ("asf_script_command::get_commands ().\n");
804 int size_left = size;
805 int size_requested = 0;
806 char** types = NULL;
807 char* start = NULL;
808 asf_script_command_entry** result = NULL;
809 asf_script_command_entry* next = NULL;
811 if (size == sizeof (asf_script_command)) {
812 //printf ("asf_script_command::get_commands (), size = %d\n", size);
813 return NULL;
816 size_left -= sizeof (asf_script_command);
818 size_requested = sizeof (char*) * (command_count + 1);
819 if (size_requested > size_left) {
820 parser->AddError ("Data corruption in script command.");
821 goto failure;
824 result = (asf_script_command_entry**) parser->MallocVerified (size_requested);
825 if (result == NULL)
826 goto failure;
828 size_requested = sizeof (char*) * (command_type_count + 1);
829 if (size_requested > size_left) {
830 parser->AddError ("Data corruption in script command.");
831 goto failure;
834 types = (char**) parser->MallocVerified (size_requested);
835 if (types == NULL)
836 goto failure;
838 if (command_types != NULL)
839 *command_types = types;
841 // Walk past by the command type table.
842 start = (sizeof (asf_script_command) + (char*) this);
843 for (int i = 0; i < command_type_count; i++) {
844 asf_word length = * (asf_word*) start;
846 // Verify data
847 size_requested = sizeof (asf_word) + sizeof (guint16) * length;
848 if (size_requested > size_left) {
849 parser->AddError ("Data corruption in script command.");
850 goto failure;
852 size_left -= size_requested;
854 // Convert strings
855 types [i] = wchar_to_utf8 (start + sizeof (asf_word), length);
856 start += size_requested;
859 // Fill in the commands table
860 next = (asf_script_command_entry*) start;
861 for (int i = 0; i < command_count; i++) {
862 result [i] = next;
864 char* tmp = (char*) next;
865 tmp += sizeof (asf_script_command_entry);
866 tmp += (next->name_length * sizeof (guint16));
868 size_requested = sizeof (asf_script_command_entry) + next->name_length * sizeof (guint16);
869 if (size_requested > size_left) {
870 parser->AddError ("Data corruption in script command.");
871 goto failure;
873 size_left -= size_requested;
875 next = (asf_script_command_entry*) tmp;
878 //printf ("asf_script_command::read_commands (): success, read %d commands and %d types.\n", command_count, command_type_count);
879 return result;
881 failure:
882 //printf ("asf_script_command::read_commands (): failure.\n");
883 g_free (result);
884 if (types != NULL) {
885 for (int i = 0; types[i]; i++)
886 g_free (types [i]);
887 g_free (types);
890 if (command_types != NULL)
891 *command_types = NULL;
893 return NULL;
897 void asf_marker_entry_dump (const asf_marker_entry* obj)
899 #ifdef ASF_DUMPING
900 asf_marker_entry* o = (asf_marker_entry*) obj;
901 ASF_DUMP ("\tASF_MARKER_ENTRY\n");
902 ASF_DUMP ("\t\toffset = %" G_GUINT64_FORMAT "\n", obj->offset);
903 ASF_DUMP ("\t\tpts = %" G_GUINT64_FORMAT "\n", obj->pts);
904 ASF_DUMP ("\t\tentry_length = %d\n", (asf_dword) obj->entry_length);
905 ASF_DUMP ("\t\tsend_time = %d\n", obj->send_time);
906 ASF_DUMP ("\t\tflags = %d\n", obj->flags);
907 ASF_DUMP ("\t\tmarker_description_length = %d\n", o->marker_description_length);
908 ASF_DUMP ("\t\tmarker_description = %s\n", o->get_marker_description ());
909 #endif
912 void asf_marker_dump (const asf_marker* obj)
914 asf_marker* o = (asf_marker*) obj;
916 ASF_DUMP ("ASF_MARKER\n");
917 ASF_DUMP ("\tid = %s\n", asf_guid_tostring (&obj->id));
918 ASF_DUMP ("\tsize = %" G_GUINT64_FORMAT "\n", obj->size);
919 ASF_DUMP ("\treserved = %s\n", asf_guid_tostring (&obj->reserved));
920 ASF_DUMP ("\tmarker_count = %u\n", (asf_dword) obj->marker_count);
921 ASF_DUMP ("\treserved2 = %u\n", (asf_dword) obj->reserved2);
922 ASF_DUMP ("\tname_length = %u\n", (asf_dword) obj->name_length);
923 ASF_DUMP ("\tname = %s\n", o->get_name ());
925 for (guint32 i = 0; i < obj->marker_count; i++) {
926 asf_marker_entry_dump (o->get_entry (i));
930 void asf_script_command_dump (ASFParser* parser, const asf_script_command* obj)
932 #ifdef ASF_DUMPING
933 asf_script_command* o = (asf_script_command*) obj;
934 guint32 i;
936 ASF_DUMP ("ASF_SCRIPT_COMMAND\n");
937 ASF_DUMP ("\tid = %s\n", asf_guid_tostring (&obj->id));
938 ASF_DUMP ("\tsize = %" G_GUINT64_FORMAT "\n", obj->size);
939 ASF_DUMP ("\treserved = %s\n", asf_guid_tostring (&obj->reserved));
940 ASF_DUMP ("\tcommand_count = %u\n", (asf_dword) obj->command_count);
941 ASF_DUMP ("\tcommand_type_count = %u\n", (asf_dword) obj->command_type_count);
943 char** command_types = NULL;
944 asf_script_command_entry** entries = NULL;
946 entries = o->get_commands (parser, &command_types);
948 for (i = 0; i < obj->command_type_count; i++) {
949 ASF_DUMP ("\tASF_SCRIPT_COMMAND_TYPE #%d\n", i);
950 ASF_DUMP ("\t\tname = %s\n", command_types [i]);
953 for (i = 0; i < obj->command_count; i++) {
954 ASF_DUMP ("\tASF_SCRIPT_COMMAND #%u\n", i);
955 asf_script_command_entry* entry = entries [i];
956 ASF_DUMP ("\t\tpts = %u\n", entry->pts);
957 ASF_DUMP ("\t\ttype_index = %d\n", (asf_dword) entry->type_index);
958 ASF_DUMP ("\t\tname_length = %d\n", (asf_dword) entry->name_length);
959 ASF_DUMP ("\t\tname = %s\n", entry->get_name ());
961 #endif
964 void asf_header_extension_dump (const asf_header_extension* obj)
966 ASF_DUMP ("ASF_HEADER_EXTENSION\n");
967 ASF_DUMP ("\tid = %s\n", asf_guid_tostring (&obj->id));
968 ASF_DUMP ("\tsize = %" G_GUINT64_FORMAT "\n", obj->size);
969 ASF_DUMP ("\treserved1 = %s\n", asf_guid_tostring (&obj->reserved1));
970 ASF_DUMP ("\treserved2 = %u\n", (asf_dword) obj->reserved2);
971 ASF_DUMP ("\tdata_size = %u\n", (asf_dword) obj->data_size);
973 asf_dword count = obj->get_object_count ();
974 asf_object** objects = obj->get_objects ();
976 for (asf_dword i = 0; i < count; i++) {
977 ASF_DUMP ("\n\textended object #%d:\n", i);
978 asf_object_dump_exact (objects [i]);
980 ASF_DUMP ("\n\n");
981 g_free (objects);
984 bool asf_extended_stream_properties_validate (const asf_extended_stream_properties* obj, ASFParser* parser)
986 if (!(asf_guid_validate (&obj->id, &asf_guids_extended_stream_properties, parser))) {
987 return false;
990 if (obj->size < 88) {
991 parser->AddError (g_strdup_printf ("Invalid size (expected >= 112, got %" G_GUINT64_FORMAT ").", obj->size));
992 return false;
995 if (obj->data_bitrate == 0) {
996 parser->AddError (g_strdup_printf ("Invalid bitrate (expected != 0)."));
997 return false;
1000 if (obj->initial_buffer_fullness > obj->buffer_size) {
1001 parser->AddError (g_strdup_printf ("Invalid initial buffer fullness (expected <= buffer size (%i), got %i).", obj->buffer_size, obj->initial_buffer_fullness));
1002 return false;
1005 if (obj->alternate_initial_buffer_fullness > obj->alternate_buffer_size) {
1006 parser->AddError (g_strdup_printf ("Invalid alternate initial buffer fullness (expected <= alternate buffer size (%i), got %i).", obj->alternate_buffer_size, obj->alternate_initial_buffer_fullness));
1007 return false;
1010 if (obj->stream_id == 0 || obj->stream_id > 127) {
1011 parser->AddError (g_strdup_printf ("Invalid stream number, must be 0 < stream number <= 127, got %i.", obj->stream_id ));
1012 return false;
1015 guint64 max_size = obj->size;
1016 guint64 stream_names_length = 0; // accumulated length of stream names
1017 guint64 payload_ex_sys_length = 0; // accumulated length of payload extension systems
1018 guint64 size = 88; // size of all the fixed fields
1020 for (gint32 i = 0; i < obj->stream_name_count; i++) {
1021 if (size + 4 > max_size) { // 4 = minimum size of stream name
1022 parser->AddError (g_strdup_printf ("Invalid stream name count."));
1023 return false;
1025 gint16 length = 4 + *(gint16 *) (((char *) obj) + 88 + stream_names_length + 2 /* offset into length */);
1026 size += length;
1027 stream_names_length += length;
1028 if (size > max_size) {
1029 parser->AddError (g_strdup_printf ("Invalid stream name."));
1030 return false;
1034 for (gint32 i = 0; i < obj->payload_extension_system_count; i++) {
1035 if (size + 22 > max_size) { // 22 = minimum size of payload extension system
1036 parser->AddError (g_strdup_printf ("Invalid payload extension system count."));
1037 return false;
1039 guint32 length = 22 + *(guint32 *) (((char *) obj) + 88 + stream_names_length + payload_ex_sys_length + 18 /* offset into length */);
1040 if (length > max_size) { // Sanity check length before doing algorithm with it to avoid overflows.
1041 parser->AddError (g_strdup_printf ("Invalid payload extension system."));
1042 return false;
1044 size += length;
1045 payload_ex_sys_length += length;
1046 if (size > max_size) {
1047 parser->AddError (g_strdup_printf ("Invalid payload extension system."));
1048 return false;
1052 return true;
1055 void asf_extended_stream_properties_dump (const asf_extended_stream_properties* obj)
1057 #ifdef ASF_DUMPING
1058 ASF_DUMP ("ASF_EXTENDED_STREAM_PROPERTIES\n");
1059 ASF_DUMP ("\tid = %s\n", asf_guid_tostring (&obj->id));
1060 ASF_DUMP ("\tsize = %" G_GUINT64_FORMAT "\n", obj->size);
1061 ASF_DUMP ("\tstart_time = %" G_GUINT64_FORMAT "\n", obj->start_time);
1062 ASF_DUMP ("\tend_time = %" G_GUINT64_FORMAT "\n", obj->end_time);
1063 ASF_DUMP ("\tdata_bitrate = %u\n", (asf_dword) obj->data_bitrate);
1064 ASF_DUMP ("\tbuffer_size = %u\n", (asf_dword) obj->buffer_size);
1065 ASF_DUMP ("\tinitial_buffer_fullness = %u\n", (asf_dword) obj->initial_buffer_fullness);
1066 ASF_DUMP ("\talternate_data_bitrate = %u\n", (asf_dword) obj->alternate_data_bitrate);
1067 ASF_DUMP ("\talternate_buffer_size = %u\n", (asf_dword) obj->alternate_buffer_size);
1068 ASF_DUMP ("\talternate_initial_buffer_fullness = %u\n", (asf_dword) obj->alternate_initial_buffer_fullness);
1069 ASF_DUMP ("\tmaximum_object_size = %u\n", (asf_dword) obj->maximum_object_size);
1070 ASF_DUMP ("\tflags = %u\n", (asf_dword) obj->flags);
1071 ASF_DUMP ("\tstream_id = %u\n", (asf_dword) obj->stream_id);
1072 ASF_DUMP ("\tstream_language_id_index = %u\n", (asf_dword) obj->stream_language_id_index);
1073 ASF_DUMP ("\taverage_time_per_frame = %" G_GUINT64_FORMAT "\n", obj->average_time_per_frame);
1074 ASF_DUMP ("\tstream_name_count = %u\n", (asf_dword) obj->stream_name_count);
1075 ASF_DUMP ("\tpayload_extension_system_count = %u\n", (asf_dword) obj->payload_extension_system_count);
1077 asf_extended_stream_name **names = obj->get_stream_names ();
1078 ASF_DUMP ("\tstream_names: %p\n", names);
1079 if (names != NULL) {
1080 for (int i = 0; names [i] != NULL; i++)
1081 asf_extended_stream_name_dump (names [i]);
1083 g_free (names);
1085 asf_payload_extension_system **systems = obj->get_payload_extension_systems ();
1086 ASF_DUMP ("\tpayload_extension_systems: %p\n", systems);
1087 if (systems != NULL) {
1088 for (int i = 0; systems [i] != NULL; i++)
1089 asf_payload_extension_system_dump (systems [i]);
1091 g_free (systems);
1093 const asf_stream_properties *asp = obj->get_stream_properties ();
1094 ASF_DUMP ("\tasf_stream_properties = %p\n", asp);
1095 if (asp != NULL)
1096 asf_stream_properties_dump (asp);
1097 #endif
1100 void asf_extended_stream_name_dump (const asf_extended_stream_name* obj)
1102 ASF_DUMP ("ASF_EXTENDED_STREAM_NAME\n");
1103 ASF_DUMP ("\tlanguage_id_index = %i\n", (int) obj->language_id_index);
1104 ASF_DUMP ("\tstream_name_length = %i\n", (int) obj->stream_name_length);
1105 ASF_DUMP ("\tstream_name = %s\n", obj->get_stream_name ());
1108 void asf_payload_extension_system_dump (const asf_payload_extension_system* obj)
1110 ASF_DUMP ("ASF_PAYLOAD_EXTENSION_SYSTEM\n");
1111 ASF_DUMP ("\textension_system_id = %s\n", asf_guid_tostring (&obj->extension_system_id));
1112 ASF_DUMP ("\textension_data_size = %i\n", (int) obj->extension_data_size);