url_fseek(s->pb, off + len, SEEK_SET);
}
+static int asf_read_file_properties(AVFormatContext *s, int64_t size)
+{
+ ASFContext *asf = s->priv_data;
+ ByteIOContext *pb = s->pb;
+
+ ff_get_guid(pb, &asf->hdr.guid);
+ asf->hdr.file_size = get_le64(pb);
+ asf->hdr.create_time = get_le64(pb);
+ get_le64(pb); /* number of packets */
+ asf->hdr.play_time = get_le64(pb);
+ asf->hdr.send_time = get_le64(pb);
+ asf->hdr.preroll = get_le32(pb);
+ asf->hdr.ignore = get_le32(pb);
+ asf->hdr.flags = get_le32(pb);
+ asf->hdr.min_pktsize = get_le32(pb);
+ asf->hdr.max_pktsize = get_le32(pb);
+ asf->hdr.max_bitrate = get_le32(pb);
+ s->packet_size = asf->hdr.max_pktsize;
+
+ return 0;
+}
+
+static int asf_read_ext_stream_properties(AVFormatContext *s, int64_t size)
+{
+ ASFContext *asf = s->priv_data;
+ ByteIOContext *pb = s->pb;
+ ff_asf_guid g;
+ int ext_len, payload_ext_ct, stream_ct, i;
+ uint32_t ext_d, leak_rate, stream_num;
+ unsigned int stream_languageid_index;
+
+ get_le64(pb); // starttime
+ get_le64(pb); // endtime
+ leak_rate = get_le32(pb); // leak-datarate
+ get_le32(pb); // bucket-datasize
+ get_le32(pb); // init-bucket-fullness
+ get_le32(pb); // alt-leak-datarate
+ get_le32(pb); // alt-bucket-datasize
+ get_le32(pb); // alt-init-bucket-fullness
+ get_le32(pb); // max-object-size
+ get_le32(pb); // flags (reliable,seekable,no_cleanpoints?,resend-live-cleanpoints, rest of bits reserved)
+ stream_num = get_le16(pb); // stream-num
+
+ stream_languageid_index = get_le16(pb); // stream-language-id-index
+ if (stream_num < 128)
+ asf->streams[stream_num].stream_language_index = stream_languageid_index;
+
+ get_le64(pb); // avg frametime in 100ns units
+ stream_ct = get_le16(pb); //stream-name-count
+ payload_ext_ct = get_le16(pb); //payload-extension-system-count
+
+ if (stream_num < 128)
+ asf->stream_bitrates[stream_num] = leak_rate;
+
+ for (i=0; i<stream_ct; i++){
+ get_le16(pb);
+ ext_len = get_le16(pb);
+ url_fseek(pb, ext_len, SEEK_CUR);
+ }
+
+ for (i=0; i<payload_ext_ct; i++){
+ ff_get_guid(pb, &g);
+ ext_d=get_le16(pb);
+ ext_len=get_le32(pb);
+ url_fseek(pb, ext_len, SEEK_CUR);
+ }
+
+ return 0;
+}
+
+static int asf_read_content_desc(AVFormatContext *s, int64_t size)
+{
+ ByteIOContext *pb = s->pb;
+ int len1, len2, len3, len4, len5;
+
+ len1 = get_le16(pb);
+ len2 = get_le16(pb);
+ len3 = get_le16(pb);
+ len4 = get_le16(pb);
+ len5 = get_le16(pb);
+ get_tag(s, "title" , 0, len1);
+ get_tag(s, "author" , 0, len2);
+ get_tag(s, "copyright", 0, len3);
+ get_tag(s, "comment" , 0, len4);
+ url_fskip(pb, len5);
+
+ return 0;
+}
+
+static int asf_read_ext_content_desc(AVFormatContext *s, int64_t size)
+{
+ ByteIOContext *pb = s->pb;
+ ASFContext *asf = s->priv_data;
+ int desc_count, i, ret;
+
+ desc_count = get_le16(pb);
+ for(i=0;i<desc_count;i++) {
+ int name_len,value_type,value_len;
+ char name[1024];
+
+ name_len = get_le16(pb);
+ if (name_len%2) // must be even, broken lavf versions wrote len-1
+ name_len += 1;
+ if ((ret = avio_get_str16le(pb, name_len, name, sizeof(name))) < name_len)
+ url_fskip(pb, name_len - ret);
+ value_type = get_le16(pb);
+ value_len = get_le16(pb);
+ if (!value_type && value_len%2)
+ value_len += 1;
+ /**
+ * My sample has that stream set to 0 maybe that mean the container.
+ * Asf stream count start at 1. I am using 0 to the container value since it's unused
+ */
+ if (!strcmp(name, "AspectRatioX")){
+ asf->dar[0].num= get_value(s->pb, value_type);
+ } else if(!strcmp(name, "AspectRatioY")){
+ asf->dar[0].den= get_value(s->pb, value_type);
+ } else
+ get_tag(s, name, value_type, value_len);
+ }
+
+ return 0;
+}
+
+static int asf_read_language_list(AVFormatContext *s, int64_t size)
+{
+ ByteIOContext *pb = s->pb;
+ ASFContext *asf = s->priv_data;
+ int j, ret;
+ int stream_count = get_le16(pb);
+ for(j = 0; j < stream_count; j++) {
+ char lang[6];
+ unsigned int lang_len = get_byte(pb);
+ if ((ret = avio_get_str16le(pb, lang_len, lang, sizeof(lang))) < lang_len)
+ url_fskip(pb, lang_len - ret);
+ if (j < 128)
+ av_strlcpy(asf->stream_languages[j], lang, sizeof(*asf->stream_languages));
+ }
+
+ return 0;
+}
+
+static int asf_read_metadata(AVFormatContext *s, int64_t size)
+{
+ ByteIOContext *pb = s->pb;
+ ASFContext *asf = s->priv_data;
+ int n, stream_num, name_len, value_len, value_type, value_num;
+ int ret, i;
+ n = get_le16(pb);
+
+ for(i=0;i<n;i++) {
+ char name[1024];
+
+ get_le16(pb); //lang_list_index
+ stream_num= get_le16(pb);
+ name_len= get_le16(pb);
+ value_type= get_le16(pb);
+ value_len= get_le32(pb);
+
+ if ((ret = avio_get_str16le(pb, name_len, name, sizeof(name))) < name_len)
+ url_fskip(pb, name_len - ret);
+ //av_log(s, AV_LOG_ERROR, "%d %d %d %d %d <%s>\n", i, stream_num, name_len, value_type, value_len, name);
+ value_num= get_le16(pb);//we should use get_value() here but it does not work 2 is le16 here but le32 elsewhere
+ url_fskip(pb, value_len - 2);
+
+ if(stream_num<128){
+ if (!strcmp(name, "AspectRatioX")) asf->dar[stream_num].num= value_num;
+ else if(!strcmp(name, "AspectRatioY")) asf->dar[stream_num].den= value_num;
+ }
+ }
+
+ return 0;
+}
+
+static int asf_read_marker(AVFormatContext *s, int64_t size)
+{
+ ByteIOContext *pb = s->pb;
+ int i, count, name_len, ret;
+ char name[1024];
+
+ get_le64(pb); // reserved 16 bytes
+ get_le64(pb); // ...
+ count = get_le32(pb); // markers count
+ get_le16(pb); // reserved 2 bytes
+ name_len = get_le16(pb); // name length
+ for(i=0;i<name_len;i++){
+ get_byte(pb); // skip the name
+ }
+
+ for(i=0;i<count;i++){
+ int64_t pres_time;
+ int name_len;
+
+ get_le64(pb); // offset, 8 bytes
+ pres_time = get_le64(pb); // presentation time
+ get_le16(pb); // entry length
+ get_le32(pb); // send time
+ get_le32(pb); // flags
+ name_len = get_le32(pb); // name length
+ if ((ret = avio_get_str16le(pb, name_len * 2, name, sizeof(name))) < name_len)
+ url_fskip(pb, name_len - ret);
+ ff_new_chapter(s, i, (AVRational){1, 10000000}, pres_time, AV_NOPTS_VALUE, name );
+ }
+
+ return 0;
+}
+
static int asf_read_header(AVFormatContext *s, AVFormatParameters *ap)
{
ASFContext *asf = s->priv_data;
memset(&asf->asfid2avid, -1, sizeof(asf->asfid2avid));
for(;;) {
uint64_t gpos= url_ftell(pb);
- int ret;
ff_get_guid(pb, &g);
gsize = get_le64(pb);
av_dlog(s, "%08"PRIx64": ", gpos);
if (gsize < 24)
return -1;
if (!ff_guidcmp(&g, &ff_asf_file_header)) {
- ff_get_guid(pb, &asf->hdr.guid);
- asf->hdr.file_size = get_le64(pb);
- asf->hdr.create_time = get_le64(pb);
- get_le64(pb); /* number of packets */
- asf->hdr.play_time = get_le64(pb);
- asf->hdr.send_time = get_le64(pb);
- asf->hdr.preroll = get_le32(pb);
- asf->hdr.ignore = get_le32(pb);
- asf->hdr.flags = get_le32(pb);
- asf->hdr.min_pktsize = get_le32(pb);
- asf->hdr.max_pktsize = get_le32(pb);
- asf->hdr.max_bitrate = get_le32(pb);
- s->packet_size = asf->hdr.max_pktsize;
+ asf_read_file_properties(s, gsize);
} else if (!ff_guidcmp(&g, &ff_asf_stream_header)) {
enum AVMediaType type;
int type_specific_size, sizeX;
pos2 = url_ftell(pb);
url_fskip(pb, gsize - (pos2 - pos1 + 24));
} else if (!ff_guidcmp(&g, &ff_asf_comment_header)) {
- int len1, len2, len3, len4, len5;
-
- len1 = get_le16(pb);
- len2 = get_le16(pb);
- len3 = get_le16(pb);
- len4 = get_le16(pb);
- len5 = get_le16(pb);
- get_tag(s, "title" , 0, len1);
- get_tag(s, "author" , 0, len2);
- get_tag(s, "copyright", 0, len3);
- get_tag(s, "comment" , 0, len4);
- url_fskip(pb, len5);
+ asf_read_content_desc(s, gsize);
} else if (!ff_guidcmp(&g, &ff_asf_language_guid)) {
- int j;
- int stream_count = get_le16(pb);
- for(j = 0; j < stream_count; j++) {
- char lang[6];
- unsigned int lang_len = get_byte(pb);
- if ((ret = avio_get_str16le(pb, lang_len, lang, sizeof(lang))) < lang_len)
- url_fskip(pb, lang_len - ret);
- if (j < 128)
- av_strlcpy(asf->stream_languages[j], lang, sizeof(*asf->stream_languages));
- }
+ asf_read_language_list(s, gsize);
} else if (!ff_guidcmp(&g, &ff_asf_extended_content_header)) {
- int desc_count, i;
-
- desc_count = get_le16(pb);
- for(i=0;i<desc_count;i++) {
- int name_len,value_type,value_len;
- char name[1024];
-
- name_len = get_le16(pb);
- if (name_len%2) // must be even, broken lavf versions wrote len-1
- name_len += 1;
- if ((ret = avio_get_str16le(pb, name_len, name, sizeof(name))) < name_len)
- url_fskip(pb, name_len - ret);
- value_type = get_le16(pb);
- value_len = get_le16(pb);
- if (!value_type && value_len%2)
- value_len += 1;
- /**
- * My sample has that stream set to 0 maybe that mean the container.
- * Asf stream count start at 1. I am using 0 to the container value since it's unused
- */
- if (!strcmp(name, "AspectRatioX")){
- asf->dar[0].num= get_value(s->pb, value_type);
- } else if(!strcmp(name, "AspectRatioY")){
- asf->dar[0].den= get_value(s->pb, value_type);
- } else
- get_tag(s, name, value_type, value_len);
- }
+ asf_read_ext_content_desc(s, gsize);
} else if (!ff_guidcmp(&g, &ff_asf_metadata_header)) {
- int n, stream_num, name_len, value_len, value_type, value_num;
- n = get_le16(pb);
-
- for(i=0;i<n;i++) {
- char name[1024];
-
- get_le16(pb); //lang_list_index
- stream_num= get_le16(pb);
- name_len= get_le16(pb);
- value_type= get_le16(pb);
- value_len= get_le32(pb);
-
- if ((ret = avio_get_str16le(pb, name_len, name, sizeof(name))) < name_len)
- url_fskip(pb, name_len - ret);
-//av_log(s, AV_LOG_ERROR, "%d %d %d %d %d <%s>\n", i, stream_num, name_len, value_type, value_len, name);
- value_num= get_le16(pb);//we should use get_value() here but it does not work 2 is le16 here but le32 elsewhere
- url_fskip(pb, value_len - 2);
-
- if(stream_num<128){
- if (!strcmp(name, "AspectRatioX")) asf->dar[stream_num].num= value_num;
- else if(!strcmp(name, "AspectRatioY")) asf->dar[stream_num].den= value_num;
- }
- }
+ asf_read_metadata(s, gsize);
} else if (!ff_guidcmp(&g, &ff_asf_ext_stream_header)) {
- int ext_len, payload_ext_ct, stream_ct;
- uint32_t ext_d, leak_rate, stream_num;
- unsigned int stream_languageid_index;
-
- get_le64(pb); // starttime
- get_le64(pb); // endtime
- leak_rate = get_le32(pb); // leak-datarate
- get_le32(pb); // bucket-datasize
- get_le32(pb); // init-bucket-fullness
- get_le32(pb); // alt-leak-datarate
- get_le32(pb); // alt-bucket-datasize
- get_le32(pb); // alt-init-bucket-fullness
- get_le32(pb); // max-object-size
- get_le32(pb); // flags (reliable,seekable,no_cleanpoints?,resend-live-cleanpoints, rest of bits reserved)
- stream_num = get_le16(pb); // stream-num
-
- stream_languageid_index = get_le16(pb); // stream-language-id-index
- if (stream_num < 128)
- asf->streams[stream_num].stream_language_index = stream_languageid_index;
-
- get_le64(pb); // avg frametime in 100ns units
- stream_ct = get_le16(pb); //stream-name-count
- payload_ext_ct = get_le16(pb); //payload-extension-system-count
-
- if (stream_num < 128)
- asf->stream_bitrates[stream_num] = leak_rate;
-
- for (i=0; i<stream_ct; i++){
- get_le16(pb);
- ext_len = get_le16(pb);
- url_fseek(pb, ext_len, SEEK_CUR);
- }
-
- for (i=0; i<payload_ext_ct; i++){
- ff_get_guid(pb, &g);
- ext_d=get_le16(pb);
- ext_len=get_le32(pb);
- url_fseek(pb, ext_len, SEEK_CUR);
- }
+ asf_read_ext_stream_properties(s, gsize);
// there could be a optional stream properties object to follow
// if so the next iteration will pick it up
v2 = get_le16(pb);
continue;
} else if (!ff_guidcmp(&g, &ff_asf_marker_header)) {
- int i, count, name_len;
- char name[1024];
-
- get_le64(pb); // reserved 16 bytes
- get_le64(pb); // ...
- count = get_le32(pb); // markers count
- get_le16(pb); // reserved 2 bytes
- name_len = get_le16(pb); // name length
- for(i=0;i<name_len;i++){
- get_byte(pb); // skip the name
- }
-
- for(i=0;i<count;i++){
- int64_t pres_time;
- int name_len;
-
- get_le64(pb); // offset, 8 bytes
- pres_time = get_le64(pb); // presentation time
- get_le16(pb); // entry length
- get_le32(pb); // send time
- get_le32(pb); // flags
- name_len = get_le32(pb); // name length
- if ((ret = avio_get_str16le(pb, name_len * 2, name, sizeof(name))) < name_len)
- url_fskip(pb, name_len - ret);
- ff_new_chapter(s, i, (AVRational){1, 10000000}, pres_time, AV_NOPTS_VALUE, name );
- }
+ asf_read_marker(s, gsize);
} else if (url_feof(pb)) {
return -1;
} else {