The tool prints out asf file structure. --- libavformat/Makefile | 3 +- tools/asfinfo.c | 521 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 523 insertions(+), 1 deletion(-) create mode 100644 tools/asfinfo.c
diff --git a/libavformat/Makefile b/libavformat/Makefile index 89d2d42..f42c19f 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -404,7 +404,8 @@ TESTPROGS = seek \ TESTPROGS-$(CONFIG_NETWORK) += noproxy -TOOLS = aviocat \ +TOOLS = asfinfo \ + aviocat \ ismindex \ pktdumper \ probetest \ diff --git a/tools/asfinfo.c b/tools/asfinfo.c new file mode 100644 index 0000000..f009fe3 --- /dev/null +++ b/tools/asfinfo.c @@ -0,0 +1,521 @@ +/* + * Copyright (c) 2014 Alexandra Hajkova + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" + +#include <ctype.h> +#include <errno.h> +#include <limits.h> +#include <math.h> +#include <signal.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> + +#include "libavutil/avstring.h" + +#include "libavformat/asf.h" +#include "libavformat/avformat.h" + +#define ASF_TYPE_AUDIO 0x2 +#define ASF_TYPE_VIDEO 0x1 +#define ASF_STREAM_NUM 0x7F +#define ASF_ERROR_CORRECTION_LENGTH_TYPE 0x60 +#define ASF_NUM_OF_PAYLOADS 0x3F + +static const char *filename; +static const char program_name[] = "asfinfo"; +static const int program_birth_year = 2014; + +static unsigned char GUID[16]; //128-bit + +typedef struct guids { + char name[100]; + char num[16]; + int (*read_object)(AVIOContext*, struct guids*, int64_t); + int is_subobject; +} guids; + +typedef struct data_properties { + uint64_t num_of_packets; + uint32_t packet_size; +} data_properties; + +static data_properties *datap = NULL; + +static guids *find_guid(unsigned char *guid, guids *g); +static int process_asf(AVIOContext *pb, int type, uint64_t size); + + +static void swap_guid(unsigned char GUID[16]) +{ + FFSWAP(unsigned char, GUID[0], GUID[3]); + FFSWAP(unsigned char, GUID[1], GUID[2]); + FFSWAP(unsigned char, GUID[4], GUID[5]); + FFSWAP(unsigned char, GUID[6], GUID[7]); +} + +static void show_usage(void) +{ + printf("ASF file format viewer\n"); + printf("usage: %s input_file\n", program_name); + printf("\n"); +} + +static uint64_t read_obj_size(AVIOContext *pb, guids *g, int64_t offset) +{ + uint64_t size; + + printf("%sASF %s Object, position: %"PRId64" bytes\n", + g->is_subobject ? " ":"", g->name, offset); + size = avio_rl64(pb); + if (size) + printf("%sObject size: %"PRIu64" bytes\n", g->is_subobject ? " ":" ", size); + else + printf(" Error: can not read object size\n"); + + return size; +} + +static void check_position(AVIOContext *pb, int64_t offset, uint64_t size) +{ + + if (avio_tell(pb) != (offset + size)) { + printf("Error! Expected position %"PRIu64", got %"PRIu64". Seeking to the expected postition.\n", + offset + size, avio_tell(pb)); + avio_seek(pb, offset + size, SEEK_SET); + } +} + +static int read_header(AVIOContext *pb, guids *g, int64_t offset) +{ + uint64_t size = read_obj_size(pb, g, offset); + avio_skip(pb, 6); + process_asf(pb, 1, offset + size); + check_position(pb, offset, size); + + return 0; +} + +static int read_metadata(AVIOContext *pb, const char *title, uint16_t len, unsigned char *ch, uint16_t max_len) +{ + printf(" %s: ", title); + memset(ch, 0, max_len); + avio_get_str16le(pb, len * sizeof(*ch), ch, len * sizeof(*ch)); + printf(" %s\n", ch); + + return 0; +} + +static int read_content(AVIOContext *pb, guids *g, int64_t offset) +{ + int i; + uint16_t len[5], max_len = 0; + const char *titles[] = { "Title", "Author", "Copyright", "Description", "Rate" }; + unsigned char *ch; + uint64_t size = read_obj_size(pb, g, offset); + + for (i = 0; i < 5; i++) { + len[i] = avio_rl16(pb); + max_len = FFMAX(max_len, len[i]); + } + ch = av_mallocz(max_len * sizeof(*ch)); + if (!ch) + return(AVERROR(ENOMEM)); + for (i = 0; i < 5; i++) + read_metadata(pb, titles[i], len[i], ch, max_len); + + av_free(ch); + check_position(pb, offset, size); + + return 0; +} + +static int read_unknown(AVIOContext *pb, guids *g, int64_t offset) +{ + uint64_t size = read_obj_size(pb, g, offset); + + avio_skip(pb, size - 24); + process_asf(pb, 1, offset + size); + check_position(pb, offset, size); + + return 0; +} + +// modified GET_STR16 from aviobuf +static int get_asf_string(AVIOContext *pb, int maxlen, char *buf, int buflen) +{ + char* q = buf; + int ret = 0; + if (buflen <= 0) + return AVERROR(EINVAL); + while (ret + 1 < maxlen) { + uint8_t tmp; + uint32_t ch; + GET_UTF16(ch, (ret += 2) <= maxlen ? avio_rl16(pb) : 0, break;) + PUT_UTF8(ch, tmp, if (q - buf < buflen - 1) *q++ = tmp;)\ + } + *q = 0; + return ret; +} + +static int read_unicode(AVIOContext *pb, const char *info) +{ + uint16_t len; + + if (len = avio_rl16(pb)) { + unsigned char *name; + len *= 2; // len is number of unicode characters - 2 bytes for each char + name = av_mallocz(len); + if (!name) + return AVERROR(ENOMEM); + get_asf_string(pb, len, name, len); + printf(" %s: %s\n", info, name); + av_free(name); + } + return 0; +} + +static int read_codec_list(AVIOContext *pb, guids *g, int64_t offset) +{ + int i, ret; + uint16_t len, type; + uint64_t size; + uint32_t n_codecs; + + size = read_obj_size(pb, g, offset); + avio_skip(pb, sizeof(GUID)); // skip field reserved for guid + n_codecs = avio_rl32(pb); + for (i = 0; i < n_codecs; i++) { + type = avio_rl16(pb); + if (type == ASF_TYPE_VIDEO) + printf(" Codec type: Video codec\n"); + else if (type == ASF_TYPE_AUDIO) + printf(" Codec type: Audio codec\n"); + else + printf(" Codec type: Unknown codec\n"); + if ((ret = read_unicode(pb, "Codec name")) < 0) + return ret; + if ((ret = read_unicode(pb, "Codec description")) < 0) + return ret; + if (len = avio_rl16(pb)) { + unsigned char *in; + in = av_mallocz(len); + if (!in) + return AVERROR(ENOMEM); + avio_read(pb, in, len); + printf(" Codec information: %s\n", in); + av_free(in); + } + } + check_position(pb, offset, size); + + return 0; +} + +static int read_properties(AVIOContext *pb, guids *g, int64_t offset) +{ + uint64_t size, num_of_packets; + uint32_t min_packet_size, max_packet_size, max_bitrate; + + size = read_obj_size(pb, g, offset); + avio_skip(pb, 16); // skip File ID + size = avio_rl64(pb); //File size + avio_skip(pb, 8); // skip creation date + num_of_packets = avio_rl64(pb); + avio_skip(pb, 28); //skip play and send duration, preroll, flags + min_packet_size = avio_rl32(pb); + max_packet_size = avio_rl32(pb); + max_bitrate = avio_rl32(pb); + printf(" File size %"PRId64", number of packets %"PRId64", min packet size %"PRId32", max packet size %"PRId32", max bitrate %"PRId32"\n", + size, num_of_packets, min_packet_size, max_packet_size, max_bitrate); + datap->num_of_packets = num_of_packets; + datap->packet_size = max_packet_size; + + return 0; +} + +#define read_length(flag, name, len) \ + do { \ + if (flag == name ## IS_BYTE) \ + len = avio_r8(pb); \ + else if (flag == name ## IS_WORD) \ + len = avio_rl16(pb); \ + else if (flag == name ## IS_DWORD) \ + len = avio_rl32(pb); \ + else \ + len = 0; \ + } while(0) + +static void read_subpayload(AVIOContext *pb, int64_t offset, uint32_t pad_len, int mult_payload) +{ + unsigned char sub_len; + uint16_t len; + int64_t sub_offset, sub; + + printf(" Sub-Payloads present.\n"); + avio_skip(pb, 1); // skip presentation time delta + if (mult_payload) + len = avio_rl16(pb); // total + sub = avio_tell(pb); + do { + sub_len = avio_r8(pb); + sub_offset = avio_tell(pb); + printf(" Sub-Payload at position %"PRIu64" of length %d\n", + sub_offset, sub_len); + avio_skip(pb, sub_len); + if (mult_payload && (avio_tell(pb) >= (sub + len))) + break; + } while (sub_offset < (offset + datap->packet_size - pad_len)); + if (!mult_payload) + avio_skip(pb, pad_len); +} + +static int read_payload(AVIOContext *pb, int64_t offset, unsigned char flags, + int multiple_payload, uint32_t pad_len) +{ + unsigned char stream_num; + uint64_t size; + int64_t off2; + uint32_t rep_len, off_len, media_len; + uint16_t pay_len; + + stream_num = avio_r8(pb); + stream_num &= ASF_STREAM_NUM; + read_length((flags & ASF_PL_MASK_MEDIA_OBJECT_NUMBER_LENGTH_FIELD_SIZE), + ASF_PL_FLAG_MEDIA_OBJECT_NUMBER_LENGTH_FIELD_, media_len); + read_length((flags & ASF_PL_MASK_OFFSET_INTO_MEDIA_OBJECT_LENGTH_FIELD_SIZE), + ASF_PL_FLAG_OFFSET_INTO_MEDIA_OBJECT_LENGTH_FIELD_, off_len); + read_length((flags & ASF_PL_MASK_REPLICATED_DATA_LENGTH_FIELD_SIZE), + ASF_PL_FLAG_REPLICATED_DATA_LENGTH_FIELD_, rep_len); + printf(" Media Object Number %"PRIu32", Offset Into Media Object %"PRIu32"\n", + media_len, off_len); + if (multiple_payload) { + if (rep_len == 1) + read_subpayload(pb, offset, pad_len, 1); + else { + avio_skip(pb, rep_len); // skip replicated data + pay_len = avio_rl16(pb); // payload length should be WORD + off2 = avio_tell(pb); + printf(" packet for stream #%u of size %"PRIu64" at position %"PRId64"\n", + stream_num, pay_len, off2); + if (pay_len > datap->packet_size) { + printf(" Error: invalid data packet size.\n"); + av_free(datap); + return AVERROR_INVALIDDATA; + } + avio_skip(pb, pay_len); + } + } else if (rep_len == 1) { + read_subpayload(pb, offset, pad_len, 0); + } else { + off2 = avio_tell(pb); + // packet size without header, can cointain replicated data or presentaion time delta before payload + // and padding after it + size = datap->packet_size - off2 + offset; + if (size > datap->packet_size) { + printf(" Error: invalid data packet size %"PRIu64" bytes.\n", size); + av_free(datap); + return AVERROR_INVALIDDATA; + } + printf(" packet for stream #%d of size %"PRIu64" at position %"PRId64"\n", stream_num, size, off2); + avio_skip(pb, size); // skip payload + } + return 0; +} + +static int read_data(AVIOContext *pb, guids *g, int64_t offset) +{ + int ret, i; + uint64_t size; + uint32_t packet_len, seq, pad_len; + unsigned char GUID[16], error_flags, len_flags, pay_flags, property_flags; + + size = read_obj_size(pb, g, offset); + ret = avio_read(pb, GUID, sizeof(GUID)); + if (ret) { + printf(" File ID "); + for (i = 0; i < 16; i++) + printf("%1.2X", GUID[i]); + } + printf("\n"); + size = avio_rl64(pb); + printf(" Number of Data packets %"PRIu64"\n", size); + avio_skip(pb, 2); // skip reserved field + for (i = 0; i < datap->num_of_packets; i++) { + offset = avio_tell(pb); + error_flags = avio_r8(pb); // read Error Correction Flags + if (error_flags & ASF_PACKET_FLAG_ERROR_CORRECTION_PRESENT) + if (!(error_flags & ASF_ERROR_CORRECTION_LENGTH_TYPE)) { + size = error_flags & ASF_PACKET_ERROR_CORRECTION_DATA_SIZE; + avio_skip(pb, size); + } + len_flags = avio_r8(pb); + property_flags = avio_r8(pb); + read_length((len_flags & ASF_PPI_MASK_PACKET_LENGTH_FIELD_SIZE), + ASF_PPI_FLAG_PACKET_LENGTH_FIELD_, packet_len); + read_length((len_flags & ASF_PPI_MASK_SEQUENCE_FIELD_SIZE), + ASF_PPI_FLAG_SEQUENCE_FIELD_, seq); + read_length((len_flags & ASF_PPI_MASK_PADDING_LENGTH_FIELD_SIZE), + ASF_PPI_FLAG_PADDING_LENGTH_FIELD_, pad_len ); + printf(" Packet length according to the Data Object %"PRIu32", Sequence %"PRIu32"\n", + packet_len, seq); + avio_skip(pb, 6); // skip timestamp and duration + if (len_flags & ASF_PPI_FLAG_MULTIPLE_PAYLOADS_PRESENT) { // Multiple Payloads present + int j, num; // number of payloads + pay_flags = avio_r8(pb); + num = pay_flags & ASF_NUM_OF_PAYLOADS; + printf("Multiple payload at one packet present: %d payloads\n", num); + for (j = 0; j < num; j++) + if ((ret = read_payload(pb, offset, property_flags, 1, pad_len)) < 0) + return ret; + avio_skip(pb, pad_len); + } else + if ((ret = read_payload(pb, offset, property_flags, 0, pad_len)) < 0) + return ret; + } + return 0; +} + +const guids gdef[] = { + {"Header", {0x75, 0xB2, 0x26, 0x30, 0x66, 0x8E, 0x11, 0xCF, 0xA6, 0xD9, 0x00, 0xAA, 0x00, 0x62, 0xCE, 0x6C}, read_header, 0}, + {"Data", {0x75, 0xB2, 0x26, 0x36, 0x66, 0x8E, 0x11, 0xCF, 0xA6, 0xD9, 0x00, 0xAA, 0x00, 0x62, 0xCE, 0x6C}, read_data, 0}, + {"Simple Index", {0x33, 0x00, 0x08, 0x90, 0xE5, 0xB1, 0x11, 0xCF, 0x89, 0xF4, 0x00, 0xA0, 0xC9, 0x03, 0x49, 0xCB}, read_unknown, 0}, + {"Content Description", {0x75, 0xB2, 0x26, 0x33, 0x66 ,0x8E, 0x11, 0xCF, 0xA6, 0xD9, 0x00, 0xAA, 0x00, 0x62, 0xCE, 0x6C}, read_content, 1}, + {"Extended Content Description", {0xD2, 0xD0, 0xA4, 0x40, 0xE3, 0x07, 0x11, 0xD2, 0x97, 0xF0, 0x00, 0xA0, 0xC9, 0x5e, 0xA8, 0x50}, read_unknown, 1}, + {"Stream Bitrate Properties", {0x7B, 0xF8, 0x75, 0xCE, 0x46, 0x8D, 0x11, 0xD1, 0x8D, 0x82, 0x00, 0x60, 0x97, 0xC9, 0xA2, 0xB2}, read_unknown, 1}, + {"File Properties", {0x8C, 0xAB, 0xDC, 0xA1, 0xA9, 0x47, 0x11, 0xCF, 0x8E, 0xE4, 0x00, 0xC0, 0x0C, 0x20, 0x53, 0x65}, read_properties, 1}, + {"Header Extension", {0x5F, 0xBF, 0x03, 0xB5, 0xA9, 0x2E, 0x11, 0xCF, 0x8E, 0xE3, 0x00, 0xC0, 0x0C, 0x20, 0x53, 0x65}, read_unknown, 1}, + {"Stream Properties", {0xB7, 0xDC, 0x07, 0x91, 0xA9, 0xB7, 0x11, 0xCF, 0x8E, 0xE6, 0x00, 0xC0, 0x0C, 0x20, 0x53, 0x65}, read_unknown, 1}, + {"Codec List", {0x86, 0xD1, 0x52, 0x40, 0x31, 0x1D, 0x11, 0xD0, 0xA3, 0xA4, 0x00, 0xA0, 0xC9, 0x03, 0x48, 0xF6}, read_codec_list, 1}, + {"Marker", {0xF4, 0x87, 0xCD, 0x01, 0xA9, 0x51, 0x11, 0xCF, 0x8E, 0xE6, 0x00, 0xC0, 0x0C, 0x20, 0x53, 0x65}, read_unknown, 1}, + {"Script Command", {0x1E, 0xFB, 0x1A, 0x30, 0x0B, 0x62, 0x11, 0xD0, 0xA3, 0x9B, 0x00, 0xA0, 0xC9, 0x03, 0x48, 0xF6}, read_unknown, 1}, + {"Language List", {0x7C, 0x43, 0x46, 0xa9, 0xef, 0xe0, 0x4B, 0xFC, 0xB2, 0x29, 0x39, 0x3e, 0xde, 0x41, 0x5c, 0x85}, read_unknown, 1}, + {"Padding", {0x18, 0x06, 0xD4, 0x74, 0xCA, 0xDF, 0x45, 0x09, 0xA4, 0xBA, 0x9A, 0xAB, 0xCB, 0x96, 0xAA, 0xE8}, read_unknown, 1}, + {"DRMv1 Header", {0x22, 0x11, 0xB3, 0xFB, 0xBD, 0x23, 0x11, 0xD2, 0xB4, 0xB7, 0x00, 0xA0, 0xC9, 0x55, 0xFC, 0x6E}, read_unknown, 1}, + {"DRMv2 Header", {0x29, 0x8A, 0xE6, 0x14, 0x26, 0x22, 0x4C, 0x17, 0xB9, 0x35, 0xDA, 0xE0, 0x7E, 0xE9, 0x28, 0x9c}, read_unknown, 1}, + {"Index", {0xD6, 0xE2, 0x29, 0xD3, 0x35, 0xDA, 0x11, 0xD1, 0x90, 0x34, 0x00, 0xA0, 0xC9, 0x03, 0x49, 0xBE}, read_unknown, 0}, + {"Media Object Index", {0xFE, 0xB1, 0x03, 0xF8, 0x12, 0xAD, 0x4C, 0x64, 0x84, 0x0F, 0x2A, 0x1D, 0x2F, 0x7A, 0xD4, 0x8C}, read_unknown, 0}, + {"Timecode Index", {0x3C, 0xB7, 0x3F, 0xD0, 0x0C, 0x4A, 0x48, 0x03, 0x95, 0x3D, 0xED, 0xF7, 0xB6, 0x22, 0x8F, 0x0C}, read_unknown, 0}, + {"Bitrate_Mutual_Exclusion", {0xD6, 0xE2, 0x29, 0xDC, 0x35, 0xDA, 0x11, 0xD1, 0x90, 0x34, 0x00, 0xA0, 0xC9, 0x03, 0x49, 0xBE}, read_unknown, 1}, + {"Error Correction", {0x75, 0xB2, 0x26, 0x35, 0x66, 0x8E, 0x11, 0xCF, 0xA6, 0xD9, 0x00, 0xAA, 0x00, 0x62, 0xCE, 0x6C}, read_unknown, 1}, + {"Content Branding", {0x22, 0x11, 0xB3, 0xFA, 0xBD, 0x23, 0x11, 0xD2, 0xB4, 0xB7, 0x00, 0xA0, 0xC9, 0x55, 0xFC, 0x6E}, read_unknown, 1}, + {"Content Encryption", {0x22, 0x11, 0xB3, 0xFB, 0xBD, 0x23, 0x11, 0xD2, 0xB4, 0xB7, 0x00, 0xA0, 0xC9, 0x55, 0xFC, 0x6E}, read_unknown, 1}, + {"Extended Content Encryption", {0x29, 0x8A, 0xE6, 0x14, 0x26, 0x22, 0x4C, 0x17, 0xB9, 0x35, 0xDA, 0xE0, 0x7E, 0xE9, 0x28, 0x9C}, read_unknown, 1}, + {"Digital Signature", {0x22, 0x11, 0xB3, 0xFC, 0xBD, 0x23, 0x11, 0xD2, 0xB4, 0xB7, 0x00, 0xA0, 0xC9, 0x55, 0xFC, 0x6E}, read_unknown, 1}, + {"Extended Stream Properties", {0x14, 0xE6, 0xA5, 0xCB, 0xC6, 0x72, 0x43, 0x32, 0x83, 0x99, 0xA9, 0x69, 0x52, 0x06, 0x5B, 0x5A}, read_unknown, 1}, + {"Advanced Mutual Exclusion", {0xA0, 0x86, 0x49, 0xCF, 0x47, 0x75, 0x46, 0x70, 0x8A, 0x16, 0x6E, 0x35, 0x35, 0x75, 0x66, 0xCD}, read_unknown, 1}, + {"Group Mutual Exclusion", {0xD1, 0x46, 0x5A, 0x40, 0x5A, 0x79, 0x43, 0x38, 0xB7, 0x1B, 0xE3, 0x6B, 0x8F, 0xD6, 0xC2, 0x49}, read_unknown, 1}, + {"Stream Prioritization", {0xD4, 0xFE, 0xD1, 0x5B, 0x88, 0xD3, 0x45, 0x4F, 0x81, 0xF0, 0xED, 0x5C, 0x45, 0x99, 0x9E, 0x24}, read_unknown, 1}, + {"Bandwidth Sharing Object", {0xA6, 0x96, 0x09, 0xE6, 0x51, 0x7B, 0x11, 0xD2, 0xB6, 0xAF, 0x00, 0xC0, 0x4F, 0xD9, 0x08, 0xE9}, read_unknown, 1}, + {"Metadata", {0xC5, 0xF8, 0xCB, 0xEA, 0x5B, 0xAF, 0x48, 0x77, 0x84, 0x67, 0xAA, 0x8C, 0x44, 0xFA, 0x4C, 0xCA}, read_unknown, 1}, + {"Audio Spread", {0xBF, 0xC3, 0xCD, 0x50, 0x61, 0x8F, 0x11, 0xCF, 0x8B, 0xB2, 0x00, 0xAA, 0x00, 0xB4, 0xE2, 0x20}, read_unknown, 1}, + {"Content Encryption System Windows Media DRM Network Devices", + {0x7A, 0x07, 0x9B, 0xB6, 0xDA, 0XA4, 0x4e, 0x12, 0xA5, 0xCA, 0x91, 0xD3, 0x8D, 0xC1, 0x1A, 0x8D}, read_unknown, 1}, + {"Mutex Language", {0xD6, 0xE2, 0x2A, 0x00, 0x25, 0xDA, 0x11, 0xD1, 0x90, 0x34, 0x00, 0xA0, 0xC9, 0x03, 0x49, 0xBE}, read_unknown, 1}, + {"Mutex Bitrate", {0xD6, 0xE2, 0x2A, 0x01, 0x25, 0xDA, 0x11, 0xD1, 0x90, 0x34, 0x00, 0xA0, 0xC9, 0x03, 0x49, 0xBE}, read_unknown, 1}, + {"Mutex Unknown", {0xD6, 0xE2, 0x2A, 0x02, 0x25, 0xDA, 0x11, 0xD1, 0x90, 0x34, 0x00, 0xA0, 0xC9, 0x03, 0x49, 0xBE}, read_unknown, 1}, + {"Bandwith Sharing Exclusive", {0xAF, 0x60, 0x60, 0xAA, 0x51, 0x97, 0x11, 0xD2, 0xB6, 0xAF, 0x00, 0xC0, 0x4F, 0xD9, 0x08, 0xE9}, read_unknown, 1}, + {"Bandwith Sharing Partial", {0xAF, 0x60, 0x60, 0xAB, 0x51, 0x97, 0x11, 0xD2, 0xB6, 0xAF, 0x00, 0xC0, 0x4F, 0xD9, 0x08, 0xE9}, read_unknown, 1}, + {"Payload Extension System Timecode", {0x39, 0x95, 0x95, 0xEC, 0x86, 0x67, 0x4E, 0x2D, 0x8F, 0xDB, 0x98, 0x81, 0x4C, 0xE7, 0x6C, 0x1E}, read_unknown, 1}, + {"Payload Extension System File Name", {0xE1, 0x65, 0xEC, 0x0E, 0x19, 0xED, 0x45, 0xD7, 0xB4, 0xA7, 0x25, 0xCB, 0xD1, 0xE2, 0x8E, 0x9B}, read_unknown, 1}, + {"Payload Extension System Content Type", {0xD5, 0x90, 0xDC, 0x20, 0x07, 0xBC, 0x43, 0x6C, 0x9C, 0xF7, 0xF3, 0xBB, 0xFB, 0xF1, 0xA4, 0xDC}, read_unknown, 1}, + {"Payload Extension System Pixel Aspect Ratio", {0x1, 0x1E, 0xE5, 0x54, 0xF9, 0xEA, 0x4B, 0xC8, 0x82, 0x1A, 0x37, 0x6B, 0x74, 0xE4, 0xC4, 0xB8}, read_unknown, 1}, + {"Payload Extension System Sample Duration", {0xC6, 0xBD, 0x94, 0x50, 0x86, 0x7F, 0x49, 0x07, 0x83, 0xA3, 0xC7, 0x79, 0x21, 0xB7, 0x33, 0xAD}, read_unknown, 1}, + {"Payload Extension System Encryption Sample ID", {0x66, 0x98, 0xB8, 0x4E, 0x0A, 0xFA, 0x43, 0x30, 0xAE, 0xB2, 0x1C, 0x0A, 0x98, 0xD7, 0xA4, 0x4D}, read_unknown, 1}, + {"Payload Extension System Degradable JPEG", {0x00, 0xE1, 0xAF, 0x06, 0x7B, 0xEC, 0x11, 0xD1, 0xA5, 0x82, 0x00, 0xC0, 0x4F, 0xC2, 0x9C, 0xFB}, read_unknown, 1}, + +}; + +static guids *find_guid(unsigned char *guid, guids *g) +{ + int j, ret; + + g = gdef; + for (j = 0; j < FF_ARRAY_ELEMS(g->num); j++) { + if (!(ret = memcmp(guid, g->num, sizeof(g->num)))) + return g; + g++; + } + return NULL; +} + +// type: 0 for top level object, 1 for subobject +static int process_asf(AVIOContext *pb, int type, uint64_t size) +{ + int ret, i; + guids *g = NULL; + unsigned char GUID[16], GUID2[16]; + int64_t offset; + + while (1) { + offset = avio_tell(pb); + if (type) + if (offset >= size) { + avio_seek(pb, size, SEEK_SET); + break; + } + if (ret = avio_read(pb, GUID, sizeof(GUID)) < 0) { + if (ret == AVERROR(EOF)) + break; + if (ret < 0) { + printf("Error while reading from the %s\n", filename); + continue; + } + } + memcpy(GUID2, GUID, 16); + swap_guid(GUID); + g = find_guid(GUID, g); + if (g) { + for (i = 0; i < 16; i++) + printf("%1.2X", GUID2[i]); + printf("\n"); + if ((ret = g->read_object(pb, g, offset)) < 0) + return ret; + } + } + return 0; +} + +int main(int argc, char **argv) +{ + AVIOContext *pb; + int ret; + + filename = argv[1]; + if (!filename) { + show_usage(); + fprintf(stderr, "An input file must be specified\n"); + exit(1); + } + av_register_all(); + if ((ret = avio_open(&pb, filename, AVIO_FLAG_READ)) < 0) { + av_log(NULL, AV_LOG_ERROR, "%s\n", filename); + avio_close(pb); + exit(1); + } + datap = av_mallocz(sizeof(*datap)); + if (!datap) + return AVERROR(ENOMEM); + process_asf(pb, 0, 0); + av_free(datap); + avio_close(pb); + return 0; +} -- 2.0.0.rc0 _______________________________________________ libav-devel mailing list libav-devel@libav.org https://lists.libav.org/mailman/listinfo/libav-devel