int64_t sub_dts;
uint8_t dts_delta; // for subpayloads
uint32_t packet_size_internal; // packet size stored inside ASFPacket, can be 0
- int64_t dts;
int64_t packet_offset; // offset of the current packet inside Data Object
uint32_t pad_len; // padding after payload
uint32_t rep_data_len;
// packet state
uint64_t sub_left; // subpayloads left or not
- int nb_sub; // number of subpayloads read so far from the current ASF packet
+ unsigned int nb_sub; // number of subpayloads read so far from the current ASF packet
uint16_t mult_sub_len; // total length of subpayloads array inside multiple payload
uint64_t nb_mult_left; // multiple payloads left
int return_subpayload;
uint64_t size = avio_rl64(pb);
int ret;
+ if (size > INT64_MAX)
+ return AVERROR_INVALIDDATA;
+
if (asf->is_header)
asf->unknown_size = size;
asf->is_header = 0;
if ((ret = detect_unknown_subobject(s, asf->unknown_offset,
asf->unknown_size)) < 0)
return ret;
- } else
+ } else {
+ if (size < 24) {
+ av_log(s, AV_LOG_ERROR, "Too small size %"PRIu64" (< 24).\n", size);
+ return AVERROR_INVALIDDATA;
+ }
avio_skip(pb, size - 24);
+ }
return 0;
}
AVIOContext *pb = s->pb;
avio_get_str16le(pb, len, ch, buflen);
- if (av_dict_set(&s->metadata, title, ch, 0) < 0)
- av_log(s, AV_LOG_WARNING, "av_dict_set failed.\n");
+ if (ch[0]) {
+ if (av_dict_set(&s->metadata, title, ch, 0) < 0)
+ av_log(s, AV_LOG_WARNING, "av_dict_set failed.\n");
+ }
return 0;
}
-static int asf_read_value(AVFormatContext *s, uint8_t *name, uint16_t name_len,
+static int asf_read_value(AVFormatContext *s, const uint8_t *name,
uint16_t val_len, int type, AVDictionary **met)
{
int ret;
av_log(s, AV_LOG_WARNING, "av_dict_set failed.\n");
} else {
char buf[256];
- if (val_len > sizeof(buf))
- return AVERROR_INVALIDDATA;
+ if (val_len > sizeof(buf)) {
+ ret = AVERROR_INVALIDDATA;
+ goto failed;
+ }
if ((ret = avio_read(pb, value, val_len)) < 0)
goto failed;
if (ret < 2 * val_len)
av_freep(&value);
return ret;
}
-
-static int asf_read_generic_value(AVFormatContext *s, uint8_t *name, uint16_t name_len,
- int type, AVDictionary **met)
+static int asf_read_generic_value(AVIOContext *pb, int type, uint64_t *value)
{
- AVIOContext *pb = s->pb;
- uint64_t value;
- char buf[32];
switch (type) {
case ASF_BOOL:
- value = avio_rl32(pb);
+ *value = avio_rl16(pb);
break;
case ASF_DWORD:
- value = avio_rl32(pb);
+ *value = avio_rl32(pb);
break;
case ASF_QWORD:
- value = avio_rl64(pb);
+ *value = avio_rl64(pb);
break;
case ASF_WORD:
- value = avio_rl16(pb);
+ *value = avio_rl16(pb);
break;
default:
- av_freep(&name);
return AVERROR_INVALIDDATA;
}
+
+ return 0;
+}
+
+static int asf_set_metadata(AVFormatContext *s, const uint8_t *name,
+ int type, AVDictionary **met)
+{
+ AVIOContext *pb = s->pb;
+ uint64_t value;
+ char buf[32];
+ int ret;
+
+ ret = asf_read_generic_value(pb, type, &value);
+ if (ret < 0)
+ return ret;
+
snprintf(buf, sizeof(buf), "%"PRIu64, value);
if (av_dict_set(met, name, buf, 0) < 0)
av_log(s, AV_LOG_WARNING, "av_dict_set failed.\n");
}
asf->asf_st[asf->nb_streams] = av_mallocz(sizeof(*asf_st));
asf_st = asf->asf_st[asf->nb_streams];
- if (!asf_st)
- return AVERROR(ENOMEM);
+ if (!asf_st) {
+ ret = AVERROR(ENOMEM);
+ goto fail;
+ }
st->disposition |= AV_DISPOSITION_ATTACHED_PIC;
- st->codec->codec_type = asf_st->type = AVMEDIA_TYPE_VIDEO;
- st->codec->codec_id = id;
+ st->codecpar->codec_type = asf_st->type = AVMEDIA_TYPE_VIDEO;
+ st->codecpar->codec_id = id;
st->attached_pic = pkt;
st->attached_pic.stream_index = asf_st->index = st->index;
st->attached_pic.flags |= AV_PKT_FLAG_KEY;
fail:
av_freep(&desc);
- av_free_packet(&pkt);
+ av_packet_unref(&pkt);
return ret;
}
-static void get_id3_tag(AVFormatContext *s, int len)
+static void get_id3_tag(AVFormatContext *s)
{
ID3v2ExtraMeta *id3v2_extra_meta = NULL;
ff_id3v2_free_extra_meta(&id3v2_extra_meta);
}
-static int process_metadata(AVFormatContext *s, uint8_t *name, uint16_t name_len,
+static int process_metadata(AVFormatContext *s, const uint8_t *name, uint16_t name_len,
uint16_t val_len, uint16_t type, AVDictionary **met)
{
int ret;
if (val_len) {
switch (type) {
case ASF_UNICODE:
- asf_read_value(s, name, name_len, val_len, type, met);
+ asf_read_value(s, name, val_len, type, met);
break;
case ASF_BYTE_ARRAY:
if (!strcmp(name, "WM/Picture")) // handle cover art
asf_read_picture(s, val_len);
else if (!strcmp(name, "ID3")) // handle ID3 tag
- get_id3_tag(s, val_len);
+ get_id3_tag(s);
else
- asf_read_value(s, name, name_len, val_len, type, met);
+ asf_read_value(s, name, val_len, type, met);
break;
case ASF_GUID:
ff_get_guid(s->pb, &guid);
break;
default:
- if ((ret = asf_read_generic_value(s, name, name_len, type, met)) < 0)
+ if ((ret = asf_set_metadata(s, name, type, met)) < 0)
return ret;
break;
}
}
- av_freep(&name);
return 0;
}
avio_get_str16le(pb, name_len, name,
name_len);
type = avio_rl16(pb);
+ // BOOL values are 16 bits long in the Metadata Object
+ // but 32 bits long in the Extended Content Description Object
+ if (type == ASF_BOOL)
+ type = ASF_DWORD;
val_len = avio_rl16(pb);
- if ((ret = process_metadata(s, name, name_len, val_len, type, &s->metadata)) < 0)
+ ret = process_metadata(s, name, name_len, val_len, type, &s->metadata);
+ av_freep(&name);
+ if (ret < 0)
return ret;
}
return st;
}
-static void asf_store_aspect_ratio(AVFormatContext *s, uint8_t st_num, uint8_t *name)
+static int asf_store_aspect_ratio(AVFormatContext *s, uint8_t st_num, uint8_t *name, int type)
{
ASFContext *asf = s->priv_data;
AVIOContext *pb = s->pb;
- uint16_t value = 0;
+ uint64_t value = 0;
+ int ret;
- value = avio_rl16(pb);
+ ret = asf_read_generic_value(pb, type, &value);
+ if (ret < 0)
+ return ret;
if (st_num < ASF_MAX_STREAMS) {
if (!strcmp(name, "AspectRatioX"))
else
asf->asf_sd[st_num].aspect_ratio.den = value;
}
+ return 0;
}
static int asf_read_metadata_obj(AVFormatContext *s, const GUIDParseTable *g)
break;
type = avio_rl16(pb);
val_len = avio_rl32(pb);
- name = av_malloc(name_len);
+ name = av_malloc(buflen);
if (!name)
return AVERROR(ENOMEM);
avio_get_str16le(pb, name_len, name,
buflen);
-
if (!strcmp(name, "AspectRatioX") || !strcmp(name, "AspectRatioY")) {
- asf_store_aspect_ratio(s, st_num, name);
+ ret = asf_store_aspect_ratio(s, st_num, name, type);
+ if (ret < 0) {
+ av_freep(&name);
+ break;
+ }
} else {
if (st_num < ASF_MAX_STREAMS) {
if ((ret = process_metadata(s, name, name_len, val_len, type,
- &asf->asf_sd[st_num].asf_met)) < 0)
+ &asf->asf_sd[st_num].asf_met)) < 0) {
+ av_freep(&name);
break;
- } else
- av_freep(&name);
+ }
+ }
}
+ av_freep(&name);
}
align_position(pb, asf->offset, size);
{
ASFContext *asf = s->priv_data;
AVIOContext *pb = s->pb;
- uint64_t creation_time;
+ time_t creation_time;
avio_rl64(pb); // read object size
avio_skip(pb, 16); // skip File ID
uint16_t size;
unsigned int tag;
- st->codec->width = avio_rl32(pb);
- st->codec->height = avio_rl32(pb);
+ st->codecpar->width = avio_rl32(pb);
+ st->codecpar->height = avio_rl32(pb);
avio_skip(pb, 1); // skip reserved flags
size = avio_rl16(pb); // size of the Format Data
tag = ff_get_bmp_header(pb, st);
- st->codec->codec_tag = tag;
- st->codec->codec_id = ff_codec_get_id(ff_codec_bmp_tags, tag);
+ st->codecpar->codec_tag = tag;
+ st->codecpar->codec_id = ff_codec_get_id(ff_codec_bmp_tags, tag);
if (size > BMP_HEADER_SIZE) {
int ret;
- st->codec->extradata_size = size - BMP_HEADER_SIZE;
- if (!(st->codec->extradata = av_malloc(st->codec->extradata_size +
- FF_INPUT_BUFFER_PADDING_SIZE))) {
- st->codec->extradata_size = 0;
+ st->codecpar->extradata_size = size - BMP_HEADER_SIZE;
+ if (!(st->codecpar->extradata = av_malloc(st->codecpar->extradata_size +
+ AV_INPUT_BUFFER_PADDING_SIZE))) {
+ st->codecpar->extradata_size = 0;
return AVERROR(ENOMEM);
}
- memset(st->codec->extradata + st->codec->extradata_size , 0,
- FF_INPUT_BUFFER_PADDING_SIZE);
- if ((ret = avio_read(pb, st->codec->extradata,
- st->codec->extradata_size)) < 0)
+ memset(st->codecpar->extradata + st->codecpar->extradata_size , 0,
+ AV_INPUT_BUFFER_PADDING_SIZE);
+ if ((ret = avio_read(pb, st->codecpar->extradata,
+ st->codecpar->extradata_size)) < 0)
return ret;
}
return 0;
if (!st)
return AVERROR(ENOMEM);
avpriv_set_pts_info(st, 32, 1, 1000); // pts should be dword, in milliseconds
- st->codec->codec_type = type;
+ st->codecpar->codec_type = type;
asf->asf_st[asf->nb_streams] = av_mallocz(sizeof(*asf_st));
if (!asf->asf_st[asf->nb_streams])
return AVERROR(ENOMEM);
asf_st = asf->asf_st[asf->nb_streams];
+ asf->nb_streams++;
asf_st->stream_index = stream_index;
asf_st->index = st->index;
asf_st->indexed = 0;
switch (type) {
case AVMEDIA_TYPE_AUDIO:
asf_st->type = AVMEDIA_TYPE_AUDIO;
- if ((ret = ff_get_wav_header(pb, st->codec, ts_data_len)) < 0)
+ if ((ret = ff_get_wav_header(s, pb, st->codecpar, ts_data_len)) < 0)
return ret;
break;
case AVMEDIA_TYPE_VIDEO:
asf_st->span = span;
asf_st->virtual_pkt_len = avio_rl16(pb);
asf_st->virtual_chunk_len = avio_rl16(pb);
+ if (!asf_st->virtual_chunk_len || !asf_st->virtual_pkt_len)
+ return AVERROR_INVALIDDATA;
avio_skip(pb, err_data_len - 5);
} else
avio_skip(pb, err_data_len - 1);
avio_skip(pb, err_data_len);
}
- asf->nb_streams++;
align_position(pb, asf->offset, size);
return 0;
if (st) {
st->start_time = start_time;
st->duration = end_time - start_time;
- st->codec->bit_rate = bitrate;
+ st->codecpar->bit_rate = bitrate;
st->avg_frame_rate.num = 10000000;
st->avg_frame_rate.den = time_per_frame;
}
uint64_t size = asf->data_size = avio_rl64(pb);
int i;
- if (!asf->data_reached && pb->seekable) {
+ if (!asf->data_reached) {
asf->data_reached = 1;
asf->data_offset = asf->offset;
}
size, asf->nb_packets);
avio_skip(pb, 2); // skip reserved field
asf->first_packet_offset = avio_tell(pb);
- align_position(pb, asf->offset, asf->data_size);
+ if (pb->seekable && !(asf->b_flags & ASF_FLAG_BROADCAST))
+ align_position(pb, asf->offset, asf->data_size);
return 0;
}
uint64_t interval; // index entry time interval in 100 ns units, usually it's 1s
uint32_t pkt_num, nb_entries;
int32_t prev_pkt_num = -1;
- int i;
+ int i, ret;
uint64_t size = avio_rl64(pb);
// simple index objects should be ordered by stream number, this loop tries to find
nb_entries = avio_rl32(pb);
for (i = 0; i < nb_entries; i++) {
pkt_num = avio_rl32(pb);
- avio_skip(pb, 2);
+ ret = avio_skip(pb, 2);
+ if (ret < 0) {
+ av_log(s, AV_LOG_ERROR, "Skipping failed in asf_read_simple_index.\n");
+ return ret;
+ }
if (prev_pkt_num != pkt_num) {
av_add_index_entry(st, asf->first_packet_offset + asf->packet_size *
pkt_num, av_rescale(interval, i, 10000),
asf_pkt->flags = 0;
asf_pkt->dts = 0;
asf_pkt->duration = 0;
- av_free_packet(&asf_pkt->avpkt);
+ av_packet_unref(&asf_pkt->avpkt);
av_init_packet(&asf_pkt->avpkt);
}
+static int asf_read_replicated_data(AVFormatContext *s, ASFPacket *asf_pkt)
+{
+ ASFContext *asf = s->priv_data;
+ AVIOContext *pb = s->pb;
+ int ret, data_size;
+
+ if (!asf_pkt->data_size) {
+ data_size = avio_rl32(pb); // read media object size
+ if (data_size <= 0)
+ return AVERROR_INVALIDDATA;
+ if ((ret = av_new_packet(&asf_pkt->avpkt, data_size)) < 0)
+ return ret;
+ asf_pkt->data_size = asf_pkt->size_left = data_size;
+ } else
+ avio_skip(pb, 4); // reading of media object size is already done
+ asf_pkt->dts = avio_rl32(pb); // read presentation time
+ if (asf->rep_data_len && (asf->rep_data_len >= 8))
+ avio_skip(pb, asf->rep_data_len - 8); // skip replicated data
+
+ return 0;
+}
+
static int asf_read_multiple_payload(AVFormatContext *s, AVPacket *pkt,
ASFPacket *asf_pkt)
{
if ((ret = asf_read_subpayload(s, pkt, 1)) < 0)
return ret;
} else {
- if (!asf_pkt->data_size) {
- asf_pkt->data_size = asf_pkt->size_left = avio_rl32(pb); // read media object size
- if (asf_pkt->data_size <= 0)
- return AVERROR_EOF;
- if ((ret = av_new_packet(&asf_pkt->avpkt, asf_pkt->data_size)) < 0)
+ if (asf->rep_data_len)
+ if ((ret = asf_read_replicated_data(s, asf_pkt)) < 0)
return ret;
- } else
- avio_skip(pb, 4); // reading of media object size is already done
- asf_pkt->dts = avio_rl32(pb); // read presentation time
- if ((asf->rep_data_len - 8) > 0)
- avio_skip(pb, asf->rep_data_len - 8); // skip replicated data
pay_len = avio_rl16(pb); // payload length should be WORD
if (pay_len > asf->packet_size) {
av_log(s, AV_LOG_ERROR,
skip = pay_len - asf_pkt->size_left;
pay_len = asf_pkt->size_left;
}
+ if (asf_pkt->size_left <= 0)
+ return AVERROR_INVALIDDATA;
if ((ret = avio_read(pb, p, pay_len)) < 0)
return ret;
if (s->key && s->keylen == 20)
return 0;
}
-static int asf_read_single_payload(AVFormatContext *s, AVPacket *pkt,
- ASFPacket *asf_pkt)
+static int asf_read_single_payload(AVFormatContext *s, ASFPacket *asf_pkt)
{
ASFContext *asf = s->priv_data;
AVIOContext *pb = s->pb;
int64_t offset;
uint64_t size;
unsigned char *p;
- int ret;
+ int ret, data_size;
if (!asf_pkt->data_size) {
- asf_pkt->data_size = asf_pkt->size_left = avio_rl32(pb); // read media object size
- if (asf_pkt->data_size <= 0)
+ data_size = avio_rl32(pb); // read media object size
+ if (data_size <= 0)
return AVERROR_EOF;
- if ((ret = av_new_packet(&asf_pkt->avpkt, asf_pkt->data_size)) < 0)
+ if ((ret = av_new_packet(&asf_pkt->avpkt, data_size)) < 0)
return ret;
+ asf_pkt->data_size = asf_pkt->size_left = data_size;
} else
avio_skip(pb, 4); // skip media object size
asf_pkt->dts = avio_rl32(pb); // read presentation time
- if ((asf->rep_data_len - 8) > 0)
+ if (asf->rep_data_len >= 8)
avio_skip(pb, asf->rep_data_len - 8); // skip replicated data
offset = avio_tell(pb);
return AVERROR_INVALIDDATA;
}
p = asf_pkt->avpkt.data + asf_pkt->data_size - asf_pkt->size_left;
- if (size > asf_pkt->size_left)
+ if (size > asf_pkt->size_left || asf_pkt->size_left <= 0)
return AVERROR_INVALIDDATA;
if (asf_pkt->size_left > size)
asf_pkt->size_left -= size;
if (asf->stream_index == asf->asf_st[i]->stream_index) {
asf_pkt = &asf->asf_st[i]->pkt;
asf_pkt->stream_index = asf->asf_st[i]->index;
- asf_pkt->dts = asf->dts;
break;
}
}
- if (!asf_pkt)
- return AVERROR_INVALIDDATA;
+ if (!asf_pkt) {
+ if (asf->packet_offset + asf->packet_size <= asf->data_offset + asf->data_size) {
+ if (!asf->packet_size) {
+ av_log(s, AV_LOG_ERROR, "Invalid packet size 0.\n");
+ return AVERROR_INVALIDDATA;
+ }
+ avio_seek(pb, asf->packet_offset + asf->packet_size, SEEK_SET);
+ av_log(s, AV_LOG_WARNING, "Skipping the stream with the invalid stream index %d.\n",
+ asf->stream_index);
+ return AVERROR(EAGAIN);
+ } else
+ return AVERROR_INVALIDDATA;
+ }
+
if (stream_num >> 7)
asf_pkt->flags |= AV_PKT_FLAG_KEY;
READ_LEN(asf->prop_flags & ASF_PL_MASK_MEDIA_OBJECT_NUMBER_LENGTH_FIELD_SIZE,
if ((ret = asf_read_subpayload(s, pkt, 1)) < 0)
return ret;
} else {
- if ((ret = asf_read_single_payload(s, pkt, asf_pkt)) < 0)
+ if ((ret = asf_read_single_payload(s, asf_pkt)) < 0)
return ret;
}
} else {
asf->packet_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_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);
+ len_flags = avio_r8(pb);
+ } else
+ len_flags = error_flags;
asf->prop_flags = avio_r8(pb);
READ_LEN(len_flags & ASF_PPI_MASK_PACKET_LENGTH_FIELD_SIZE,
ASF_PPI_FLAG_PACKET_LENGTH_FIELD_, asf->packet_size_internal);
if (p > asf_pkt->avpkt.data + asf_pkt->data_size)
break;
}
- av_free_packet(&asf_pkt->avpkt);
+ av_packet_unref(&asf_pkt->avpkt);
asf_pkt->avpkt = pkt;
return 0;
while (!pb->eof_reached) {
if (asf->state == PARSE_PACKET_HEADER) {
asf_read_packet_header(s);
+ if (pb->eof_reached)
+ break;
if (!asf->nb_mult_left)
asf->state = READ_SINGLE;
else
asf->state = READ_MULTI;
}
- if ((ret = asf_read_payload(s, pkt)) < 0)
+ ret = asf_read_payload(s, pkt);
+ if (ret == AVERROR(EAGAIN)) {
+ asf->state = PARSE_PACKET_HEADER;
+ continue;
+ }
+ else if (ret < 0)
return ret;
+
switch (asf->state) {
case READ_SINGLE:
if (!asf->sub_left)
case READ_MULTI_SUB:
if (!asf->sub_left && !asf->nb_mult_left) {
asf->state = PARSE_PACKET_HEADER;
- if (!asf->return_subpayload)
+ if (!asf->return_subpayload &&
+ (avio_tell(pb) <= asf->packet_offset +
+ asf->packet_size - asf->pad_len))
avio_skip(pb, asf->pad_len); // skip padding
if (asf->packet_offset + asf->packet_size > avio_tell(pb))
avio_seek(pb, asf->packet_offset + asf->packet_size, SEEK_SET);
case READ_MULTI:
if (!asf->nb_mult_left) {
asf->state = PARSE_PACKET_HEADER;
- if (!asf->return_subpayload) {
+ if (!asf->return_subpayload &&
+ (avio_tell(pb) <= asf->packet_offset +
+ asf->packet_size - asf->pad_len))
avio_skip(pb, asf->pad_len); // skip padding
- }
if (asf->packet_offset + asf->packet_size > avio_tell(pb))
avio_seek(pb, asf->packet_offset + asf->packet_size, SEEK_SET);
}
ASFContext *asf = s->priv_data;
int i;
- for (i = 0; i < asf->nb_streams; i++) {
- av_free_packet(&asf->asf_st[i]->pkt.avpkt);
- av_freep(&asf->asf_st[i]);
+ for (i = 0; i < ASF_MAX_STREAMS; i++) {
av_dict_free(&asf->asf_sd[i].asf_met);
+ if (i < asf->nb_streams) {
+ av_packet_unref(&asf->asf_st[i]->pkt.avpkt);
+ av_freep(&asf->asf_st[i]);
+ }
}
+ asf->nb_streams = 0;
return 0;
}
asf->nb_sub = 0;
asf->prop_flags = 0;
asf->sub_dts = 0;
- asf->dts = 0;
for (i = 0; i < asf->nb_streams; i++) {
ASFPacket *pkt = &asf->asf_st[i]->pkt;
pkt->size_left = 0;
pkt->flags = 0;
pkt->dts = 0;
pkt->duration = 0;
- av_free_packet(&pkt->avpkt);
+ av_packet_unref(&pkt->avpkt);
av_init_packet(&pkt->avpkt);
}
}
}
if (st_found)
break;
- av_free_packet(&pkt);
+ av_packet_unref(&pkt);
}
*pos = pkt_pos;
- av_free_packet(&pkt);
+ av_packet_unref(&pkt);
return dts;
}
} else {
if ((ret = ff_seek_frame_binary(s, stream_index, timestamp, flags)) < 0)
return ret;
-
- // asf_read_timestamp is called inside ff_seek_frame_binary and leaves state dirty,
- // so reset_packet_state have to be called after it.
- reset_packet_state(s);
}
+ reset_packet_state(s);
+
return 0;
}
int ret;
while (avio_tell(pb) <= offset + size) {
+ if (avio_tell(pb) == asf->offset)
+ break;
asf->offset = avio_tell(pb);
if ((ret = ff_get_guid(pb, &guid)) < 0)
return ret;
*/
while (1) {
// for the cases when object size is invalid
- if (avio_tell(pb) == asf->offset) {
- if (asf->data_reached)
- avio_seek(pb, asf->first_packet_offset, SEEK_SET);
+ if (avio_tell(pb) == asf->offset)
break;
- }
asf->offset = avio_tell(pb);
if ((ret = ff_get_guid(pb, &guid)) < 0) {
- if (ret == AVERROR_EOF && asf->data_reached) {
- avio_seek(pb, asf->first_packet_offset, SEEK_SET);
+ if (ret == AVERROR_EOF && asf->data_reached)
break;
- } else
- return ret;
+ else
+ goto failed;
}
g = find_guid(guid);
if (g) {
asf->unknown_offset = asf->offset;
asf->is_header = 1;
if ((ret = g->read_object(s, g)) < 0)
- return ret;
+ goto failed;
} else {
size = avio_rl64(pb);
align_position(pb, asf->offset, size);
}
- if (asf->data_reached && !pb->seekable)
+ if (asf->data_reached && (!pb->seekable || (asf->b_flags & ASF_FLAG_BROADCAST)))
break;
}
+ if (!asf->data_reached) {
+ av_log(s, AV_LOG_ERROR, "Data Object was not found.\n");
+ ret = AVERROR_INVALIDDATA;
+ goto failed;
+ }
+ if (pb->seekable)
+ avio_seek(pb, asf->first_packet_offset, SEEK_SET);
+
for (i = 0; i < asf->nb_streams; i++) {
const char *rfc1766 = asf->asf_sd[asf->asf_st[i]->lang_idx].langs;
AVStream *st = s->streams[asf->asf_st[i]->index];
}
return 0;
+
+failed:
+ asf_read_close(s);
+ return ret;
}
AVInputFormat ff_asf_demuxer = {