Quoting Alexandra Hájková (2015-03-26 10:06:07)
> The old one is the result of the reverse engineering and guesswork.
> The new one has been written following the now-available specification.
> 
> This work is part of Outreach Program for Women Summer 2014 activities
> for the Libav project.
> 
> The fate references had to be changed because the old demuxer truncates
> the last frame in some cases, the new one handles it properly.
> The seek-test reference is changed because seeking works differently
> in the new demuxer. When seeking, the packet is not read from the stream
> directly, but it is rather constructed by the demuxer. That is why
> position is -1 now in the reference.
> ---
>  libavformat/asf.h             |   21 -
>  libavformat/asfdec.c          | 2494 
> +++++++++++++++++++++--------------------
>  libavformat/asfenc.c          |   24 +-
>  tests/fate/wma.mak            |    2 +-
>  tests/ref/fate/lossless-wma   |    2 +-
>  tests/ref/fate/wmv8-drm-nodec |    1 -
>  tests/ref/seek/lavf-asf       |   54 +-
>  7 files changed, 1357 insertions(+), 1241 deletions(-)
> 
> diff --git a/libavformat/asf.h b/libavformat/asf.h
> index 2f6722a..7ac28db 100644
> --- a/libavformat/asf.h
> +++ b/libavformat/asf.h
> @@ -28,27 +28,6 @@
>  
>  #define PACKET_SIZE 3200
>  
> -typedef struct ASFStream {
> -    int num;
> -    unsigned char seq;
> -    /* use for reading */
> -    AVPacket pkt;
> -    int frag_offset;
> -    int timestamp;
> -    int64_t duration;
> -
> -    int ds_span;                /* descrambling  */
> -    int ds_packet_size;
> -    int ds_chunk_size;
> -
> -    int64_t packet_pos;
> -
> -    uint16_t stream_language_index;
> -
> -    int      palette_changed;
> -    uint32_t palette[256];
> -} ASFStream;
> -
>  typedef struct ASFMainHeader {
>      ff_asf_guid guid;                  ///< generated by client computer
>      uint64_t file_size;         /**< in bytes
> diff --git a/libavformat/asfdec.c b/libavformat/asfdec.c
> index fac5806..ca2fb3f 100644
> --- a/libavformat/asfdec.c
> +++ b/libavformat/asfdec.c
> @@ -1,6 +1,6 @@
>  /*
> - * ASF compatible demuxer
> - * Copyright (c) 2000, 2001 Fabrice Bellard
> + * Microsoft Advanced Streaming Format demuxer
> + * Copyright (c) 2014 Alexandra Hájková
>   *
>   * This file is part of Libav.
>   *
> @@ -19,8 +19,6 @@
>   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 
> USA
>   */
>  
> -#include <inttypes.h>
> -
>  #include "libavutil/attributes.h"
>  #include "libavutil/avassert.h"
>  #include "libavutil/avstring.h"
> @@ -30,6 +28,8 @@
>  #include "libavutil/internal.h"
>  #include "libavutil/mathematics.h"
>  #include "libavutil/opt.h"
> +#include "libavutil/time_internal.h"
> +
>  #include "avformat.h"
>  #include "avio_internal.h"
>  #include "avlanguage.h"
> @@ -39,153 +39,291 @@
>  #include "asf.h"
>  #include "asfcrypt.h"
>  
> +#define ASF_BOOL                              0x2
> +#define ASF_WORD                              0x5
> +#define ASF_GUID                              0x6
> +#define ASF_DWORD                             0x3
> +#define ASF_QWORD                             0x4
> +#define ASF_UNICODE                           0x0
> +#define ASF_FLAG_BROADCAST                    0x1
> +#define ASF_BYTE_ARRAY                        0x1
> +#define ASF_TYPE_AUDIO                        0x2
> +#define ASF_TYPE_VIDEO                        0x1
> +#define ASF_STREAM_NUM                        0x7F
> +#define ASF_MAX_STREAMS                       128
> +#define BMP_HEADER_SIZE                       40
> +#define ASF_NUM_OF_PAYLOADS                   0x3F
> +#define ASF_ERROR_CORRECTION_LENGTH_TYPE      0x60
> +#define ASF_PACKET_ERROR_CORRECTION_DATA_SIZE 0x2
> +
> +typedef struct GUIDParseTable {
> +    const char *name;
> +    ff_asf_guid guid;
> +    int (*read_object)(AVFormatContext *, const struct GUIDParseTable *);
> +    int is_subobject;
> +} GUIDParseTable;
> +
> +typedef struct ASFPacket {
> +    AVPacket avpkt;
> +    int64_t dts;
> +    uint32_t frame_num; // ASF payloads with the same number are parts of 
> the same frame
> +    int flags;
> +    int data_size;
> +    int duration;
> +    int size_left;
> +    uint8_t stream_index;
> +} ASFPacket;
> +
> +typedef struct ASFStream {
> +    uint8_t stream_index; //from packet header
> +    int index;  // stream index in AVFormatContext, set in 
> asf_read_stream_properties
> +    int type;
> +    int indexed; // added index entries from the Simple Index Object or not
> +    int8_t span;   // for deinterleaving
> +    uint16_t virtual_pkt_len;
> +    uint16_t virtual_chunk_len;
> +    int16_t lang_idx;
> +    ASFPacket *pkt;

Why is this allocated separately?

> +} ASFStream;
> +
>  typedef struct ASFContext {
> -    const AVClass *class;
> -    int asfid2avid[128];                 ///< conversion table from asf ID 2 
> AVStream ID
> -    ASFStream streams[128];              ///< it's max number and it's not 
> that big
> -    uint32_t stream_bitrates[128];       ///< max number of streams, bitrate 
> for each (for streaming)
> -    AVRational dar[128];
> -    char stream_languages[128][6];       ///< max number of streams, 
> language for each (RFC1766, e.g. en-US)
> -    /* non streamed additonnal info */
> -    /* packet filling */
> -    int packet_size_left;
> -    /* only for reading */
> -    uint64_t data_offset;                ///< beginning of the first data 
> packet
> -    uint64_t data_object_offset;         ///< data object offset (excl. GUID 
> & size)
> -    uint64_t data_object_size;           ///< size of the data object
> -    int index_read;
> -
> -    ASFMainHeader hdr;
> -
> -    int packet_flags;
> -    int packet_property;
> -    int packet_timestamp;
> -    int packet_segsizetype;
> -    int packet_segments;
> -    int packet_seq;
> -    int packet_replic_size;
> -    int packet_key_frame;
> -    int packet_padsize;
> -    unsigned int packet_frag_offset;
> -    unsigned int packet_frag_size;
> -    int64_t packet_frag_timestamp;
> -    int packet_multi_size;
> -    int packet_obj_size;
> -    int packet_time_delta;
> -    int packet_time_start;
> -    int64_t packet_pos;
> -
> -    int stream_index;
> -
> -    ASFStream *asf_st;                   ///< currently decoded stream
> -
> -    int no_resync_search;
> -    int export_xmp;
> +    int data_reached;
> +    int is_simple_index; // is simple index present or not 1/0
> +    int is_header;
> +
> +    uint64_t preroll;
> +    uint64_t nb_packets;      // ASF packets
> +    uint32_t packet_size;
> +    int64_t send_time;
> +    int duration;
> +
> +    uint32_t b_flags;    // flags with broadcast flag
> +    uint32_t prop_flags; // file properties object flags
> +
> +    uint64_t data_size; // data object size
> +    int64_t header_obj_size;
> +    int64_t unknown_size; // size of the unknown object

Why are those signed?

> +
> +    // presentation time offset, equal for all streams, should be equal to 
> send time, !100-nanosecond units
> +    uint64_t time_offset;

1) the comment is confusing
2) this value should be per-stream
2) it does not seem to be actually used

> +    int64_t offset; // offset of the current object

This looks more like current state rather than an immutable file
property, so it should be placed with other state variables

> +    int64_t data_offset;
> +    int64_t first_packet_offset; // packet offset
> +    int64_t unknown_offset;   // for top level header objects or subobjects 
> without specified behavior
> +
> +    // ASF file must not contain more than 128 streams according to the 
> specification
> +    ASFStream *asf_st[ASF_MAX_STREAMS];
> +    int nb_streams;
> +    int stream_index; //from packet header, for the subpayload case

As above.

> +    char langs[ASF_MAX_STREAMS][100];
> +
> +    // packet parameteres
> +    uint64_t sub_header_offset; // offset of subplayload header
> +    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
> +    uint16_t mult_sub_len; // total length of subpayloads array inside 
> multiple payload
> +    uint64_t nb_mult_left; // multiple payloads left
> +    int return_subpayload;
> +    enum {
> +        PARSE_PACKET_HEADER,
> +        READ_SINGLE,
> +        READ_MULTI,
> +        READ_MULTI_SUB
> +    } state;
>  } ASFContext;
>  
> -static const AVOption options[] = {
> -    { "no_resync_search", "Don't try to resynchronize by looking for a 
> certain optional start code", offsetof(ASFContext, no_resync_search), 
> AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, AV_OPT_FLAG_DECODING_PARAM },
> -    { "export_xmp", "Export full XMP metadata", offsetof(ASFContext, 
> export_xmp), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, AV_OPT_FLAG_DECODING_PARAM 
> },
> -    { NULL },
> -};
> +static int detect_unknown_subobject(AVFormatContext *s, int64_t offset, 
> int64_t size);
> +static const GUIDParseTable *find_guid(ff_asf_guid guid);
>  
> -static const AVClass asf_class = {
> -    .class_name = "asf demuxer",
> -    .item_name  = av_default_item_name,
> -    .option     = options,
> -    .version    = LIBAVUTIL_VERSION_INT,
> -};
> +static int asf_probe(AVProbeData *pd)
> +{
> +    /* check file header */
> +    if (!ff_guidcmp(pd->buf, &ff_asf_header))
> +        return AVPROBE_SCORE_MAX;
> +    else
> +        return 0;
> +}
>  
> -#undef NDEBUG
> -#include <assert.h>
> +static void swap_guid(ff_asf_guid guid)
> +{
> +    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]);
> +}
>  
> -#define ASF_MAX_STREAMS 127
> -#define FRAME_HEADER_SIZE 17
> -// Fix Me! FRAME_HEADER_SIZE may be different.
> +static void align_position(AVIOContext *pb,  int64_t offset, uint64_t size)
> +{
> +    if (avio_tell(pb) != offset + size)
> +        avio_seek(pb, offset + size, SEEK_SET);
> +}
>  
> -static const ff_asf_guid index_guid = {
> -    0x90, 0x08, 0x00, 0x33, 0xb1, 0xe5, 0xcf, 0x11, 0x89, 0xf4, 0x00, 0xa0, 
> 0xc9, 0x03, 0x49, 0xcb
> -};
> +static int asf_read_unknown(AVFormatContext *s, const GUIDParseTable *g)
> +{
> +    ASFContext *asf = s->priv_data;
> +    AVIOContext *pb = s->pb;
> +    uint64_t size   = avio_rl64(pb);
> +    int ret;
> +
> +    if (asf->is_header)
> +        asf->unknown_size = size;
> +    asf->is_header = 0;
> +    if (!g->is_subobject) {
> +        if (!(ret = strcmp(g->name, "Header Extension")))
> +            avio_skip(pb, 22); // skip reserved fields and Data Size
> +        if ((ret = detect_unknown_subobject(s, asf->unknown_offset,
> +                                            asf->unknown_size)) < 0)
> +            return ret;
> +    } else
> +        avio_skip(pb, size - 24);
>  
> -#ifdef DEBUG
> -static const ff_asf_guid stream_bitrate_guid = { /* (http://get.to/sdp) */
> -    0xce, 0x75, 0xf8, 0x7b, 0x8d, 0x46, 0xd1, 0x11, 0x8d, 0x82, 0x00, 0x60, 
> 0x97, 0xc9, 0xa2, 0xb2
> -};
> +    return 0;
> +}
>  
> -#define PRINT_IF_GUID(g, cmp) \
> -    if (!ff_guidcmp(g, &cmp)) \
> -        av_dlog(NULL, "(GUID: %s) ", # cmp)
> +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 void print_guid(ff_asf_guid *g)
> +static int asf_read_marker(AVFormatContext *s, const GUIDParseTable *g)
>  {
> -    int i;
> -    PRINT_IF_GUID(g, ff_asf_header);
> -    else PRINT_IF_GUID(g, ff_asf_file_header);
> -    else PRINT_IF_GUID(g, ff_asf_stream_header);
> -    else PRINT_IF_GUID(g, ff_asf_audio_stream);
> -    else PRINT_IF_GUID(g, ff_asf_audio_conceal_none);
> -    else PRINT_IF_GUID(g, ff_asf_video_stream);
> -    else PRINT_IF_GUID(g, ff_asf_video_conceal_none);
> -    else PRINT_IF_GUID(g, ff_asf_command_stream);
> -    else PRINT_IF_GUID(g, ff_asf_comment_header);
> -    else PRINT_IF_GUID(g, ff_asf_codec_comment_header);
> -    else PRINT_IF_GUID(g, ff_asf_codec_comment1_header);
> -    else PRINT_IF_GUID(g, ff_asf_data_header);
> -    else PRINT_IF_GUID(g, index_guid);
> -    else PRINT_IF_GUID(g, ff_asf_head1_guid);
> -    else PRINT_IF_GUID(g, ff_asf_head2_guid);
> -    else PRINT_IF_GUID(g, ff_asf_my_guid);
> -    else PRINT_IF_GUID(g, ff_asf_ext_stream_header);
> -    else PRINT_IF_GUID(g, ff_asf_extended_content_header);
> -    else PRINT_IF_GUID(g, ff_asf_ext_stream_embed_stream_header);
> -    else PRINT_IF_GUID(g, ff_asf_ext_stream_audio_stream);
> -    else PRINT_IF_GUID(g, ff_asf_metadata_header);
> -    else PRINT_IF_GUID(g, ff_asf_metadata_library_header);
> -    else PRINT_IF_GUID(g, ff_asf_marker_header);
> -    else PRINT_IF_GUID(g, stream_bitrate_guid);
> -    else PRINT_IF_GUID(g, ff_asf_language_guid);
> -    else
> -        av_dlog(NULL, "(GUID: unknown) ");
> -    for (i = 0; i < 16; i++)
> -        av_dlog(NULL, " 0x%02x,", (*g)[i]);
> -    av_dlog(NULL, "}\n");
> +    ASFContext *asf = s->priv_data;
> +    AVIOContext *pb = s->pb;
> +    uint64_t size   = avio_rl64(pb);
> +    int i, nb_markers, ret;
> +    size_t len;
> +    char name[1024];
> +
> +    avio_skip(pb, 8);
> +    avio_skip(pb, 8); // skip reserved GUID
> +    nb_markers = avio_rl32(pb);
> +    avio_skip(pb, 2); // skip reserved field
> +    len = avio_rl16(pb);
> +    for (i = 0; i < len; i++)
> +        avio_skip(pb, 1);
> +
> +    for (i = 0; i < nb_markers; i++) {
> +        int64_t pts;
> +
> +        avio_skip(pb, 8);
> +        pts = avio_rl64(pb);
> +        pts -= asf->preroll * 10000;
> +        avio_skip(pb, 2); // entry length
> +        avio_skip(pb, 4); // send time
> +        avio_skip(pb, 4); // flags
> +        len = avio_rl32(pb);
> +
> +        if ((ret = avio_get_str16le(pb, len, name,
> +                                    sizeof(name))) < len)
> +            avio_skip(pb, len - ret);
> +        avpriv_new_chapter(s, i, (AVRational) { 1, 10000000 }, pts,
> +                           AV_NOPTS_VALUE, name);
> +    }
> +    align_position(pb, asf->offset, size);
> +
> +    return 0;
>  }
> -#undef PRINT_IF_GUID
> -#else
> -#define print_guid(g)
> -#endif
>  
> -static int asf_probe(AVProbeData *pd)
> +static int asf_read_metadata(AVFormatContext *s, const char *title, uint16_t 
> len,
> +                             unsigned char *ch, uint16_t buflen)
>  {
> -    /* check file header */
> -    if (!ff_guidcmp(pd->buf, &ff_asf_header))
> -        return AVPROBE_SCORE_MAX;
> -    else
> -        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");
> +
> +    return 0;
> +}
> +
> +static int asf_read_value(AVFormatContext *s, uint8_t *name,
> +                      uint16_t val_len, int type, AVDictionary **met)

Broken indentation.

> +{
> +    int ret;
> +    uint8_t *value  = av_malloc(val_len);

The malloc is easy to miss there, it would be better to have it after
the variable declarations.

> +    uint16_t buflen = 2 * val_len + 1;
> +    AVIOContext *pb = s->pb;
> +
> +    if (!value)
> +        return AVERROR(ENOMEM);
> +    if (type == ASF_UNICODE) {
> +        // get_asf_string reads UTF-16 and converts it to UTF-8 which needs 
> longer buffer
> +        if ((ret = get_asf_string(pb, val_len, value, buflen)) < 0)

The buffer size is wrong.

> +            return ret;

memleak
same below

> +        if (av_dict_set(met, name, value, 0) < 0)
> +            av_log(s, AV_LOG_WARNING, "av_dict_set failed.\n");
> +    } else {
> +        char buf[32];
> +        if ((ret = avio_read(pb, value, val_len)) < 0)
> +            return ret;
> +        if (ret < 2 * val_len)
> +            value[ret] = '\0';
> +        else
> +            value[2 * val_len - 1] = '\0';
> +        snprintf(buf, sizeof(buf), "%s", value);
> +        if (av_dict_set(met, name, buf, 0) < 0)
> +            av_log(s, AV_LOG_WARNING, "av_dict_set failed.\n");
> +    }
> +    av_freep(&value);
> +
> +    return 0;
>  }
>  
> -/* size of type 2 (BOOL) is 32bit for "Extended Content Description Object"
> - * but 16 bit for "Metadata Object" and "Metadata Library Object" */
> -static int get_value(AVIOContext *pb, int type, int type2_size)
> +static int asf_read_generic_value(AVFormatContext *s, int8_t *name, int type)
>  {
> +    AVIOContext *pb = s->pb;
> +    uint64_t value;
> +    char buf[32];
> +
>      switch (type) {
> -    case 2:
> -        return (type2_size == 32) ? avio_rl32(pb) : avio_rl16(pb);
> -    case 3:
> -        return avio_rl32(pb);
> -    case 4:
> -        return avio_rl64(pb);
> -    case 5:
> -        return avio_rl16(pb);
> +    case ASF_BOOL:
> +        value = avio_rl32(pb);
> +        break;
> +    case ASF_DWORD:
> +        value = avio_rl32(pb);
> +        break;
> +    case ASF_QWORD:
> +        value = avio_rl64(pb);
> +        break;
> +    case ASF_WORD:
> +        value = avio_rl16(pb);
> +        break;
>      default:
> -        return INT_MIN;
> +        return AVERROR_INVALIDDATA;
>      }
> +    snprintf(buf, sizeof(buf), "%"PRIu64, value);
> +    if (av_dict_set(&s->metadata, name, buf, 0) < 0)
> +        av_log(s, AV_LOG_WARNING, "av_dict_set failed.\n");
> +
> +    return 0;
>  }
>  
>  /* MSDN claims that this should be "compatible with the ID3 frame, APIC",
>   * but in reality this is only loosely similar */
>  static int asf_read_picture(AVFormatContext *s, int len)
>  {
> +    ASFContext *asf       = s->priv_data;
>      AVPacket pkt          = { 0 };
>      const CodecMime *mime = ff_id3v2_mime_tags;
>      enum  AVCodecID id    = AV_CODEC_ID_NONE;
> @@ -193,6 +331,7 @@ static int asf_read_picture(AVFormatContext *s, int len)
>      uint8_t  *desc = NULL;
>      AVStream   *st = NULL;
>      int ret, type, picsize, desc_len;
> +    ASFStream *asf_st;
>  
>      /* type + picsize + mime + desc */
>      if (len < 1 + 4 + 2 + 2) {
> @@ -249,19 +388,29 @@ static int asf_read_picture(AVFormatContext *s, int len)
>          ret = AVERROR(ENOMEM);
>          goto fail;
>      }
> +    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);
> +    asf_st->pkt = NULL;
> +
>      st->disposition              |= AV_DISPOSITION_ATTACHED_PIC;
> -    st->codec->codec_type         = AVMEDIA_TYPE_VIDEO;
> +    st->codec->codec_type         = asf_st->type = AVMEDIA_TYPE_VIDEO;
>      st->codec->codec_id           = id;
>      st->attached_pic              = pkt;
> -    st->attached_pic.stream_index = st->index;
> +    st->attached_pic.stream_index = asf_st->index = st->index;
>      st->attached_pic.flags       |= AV_PKT_FLAG_KEY;
>  
> -    if (*desc)
> -        av_dict_set(&st->metadata, "title", desc, AV_DICT_DONT_STRDUP_VAL);
> -    else
> +    asf->nb_streams++;
> +
> +    if (*desc) {
> +        if (av_dict_set(&st->metadata, "title", desc, 
> AV_DICT_DONT_STRDUP_VAL) < 0)
> +            av_log(s, AV_LOG_WARNING, "av_dict_set failed.\n");
> +    } else
>          av_freep(&desc);
>  
> -    av_dict_set(&st->metadata, "comment", ff_id3v2_picture_types[type], 0);
> +    if (av_dict_set(&st->metadata, "comment", ff_id3v2_picture_types[type], 
> 0) < 0)
> +        av_log(s, AV_LOG_WARNING, "av_dict_set failed.\n");
>  
>      return 0;
>  
> @@ -281,1236 +430,1206 @@ static void get_id3_tag(AVFormatContext *s, int len)
>      ff_id3v2_free_extra_meta(&id3v2_extra_meta);
>  }
>  
> -static void get_tag(AVFormatContext *s, const char *key, int type, int len, 
> int type2_size)
> +static int process_metadata(AVFormatContext *s, uint8_t *name, uint16_t 
> val_len,
> +                            uint16_t type, AVDictionary **met)
>  {
> -    ASFContext *asf = s->priv_data;
> -    char *value = NULL;
> -    int64_t off = avio_tell(s->pb);
> -
> -    if ((unsigned)len >= (UINT_MAX - 1) / 2)
> -        return;
> -
> -    if (!asf->export_xmp && !strncmp(key, "xmp", 3))
> -        goto finish;
> +    int ret;
> +    ff_asf_guid guid;
>  
> -    value = av_malloc(2 * len + 1);
> -    if (!value)
> -        goto finish;
> -
> -    if (type == 0) {         // UTF16-LE
> -        avio_get_str16le(s->pb, len, value, 2 * len + 1);
> -    } else if (type == 1) {  // byte array
> -        if (!strcmp(key, "WM/Picture")) { // handle cover art
> -            asf_read_picture(s, len);
> -        } else if (!strcmp(key, "ID3")) { // handle ID3 tag
> -            get_id3_tag(s, len);
> -        } else {
> -            av_log(s, AV_LOG_VERBOSE, "Unsupported byte array in tag %s.\n", 
> key);
> +    if (val_len) {
> +        switch (type) {
> +        case ASF_UNICODE:
> +            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);
> +            else
> +                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, type)) < 0)
> +                return ret;
> +            break;
>          }
> -        goto finish;
> -    } else if (type > 1 && type <= 5) {  // boolean or DWORD or QWORD or WORD
> -        uint64_t num = get_value(s->pb, type, type2_size);
> -        snprintf(value, len, "%"PRIu64, num);
> -    } else if (type == 6) { // (don't) handle GUID
> -        av_log(s, AV_LOG_DEBUG, "Unsupported GUID value in tag %s.\n", key);
> -        goto finish;
> -    } else {
> -        av_log(s, AV_LOG_DEBUG,
> -               "Unsupported value type %d in tag %s.\n", type, key);
> -        goto finish;
>      }
> -    if (*value)
> -        av_dict_set(&s->metadata, key, value, 0);
> +    av_freep(&name);
>  
> -finish:
> -    av_freep(&value);
> -    avio_seek(s->pb, off + len, SEEK_SET);
> +    return 0;
>  }
>  
> -static int asf_read_file_properties(AVFormatContext *s, int64_t size)
> +static int asf_read_ext_content(AVFormatContext *s, const GUIDParseTable *g)
>  {
> -    ASFContext *asf = s->priv_data;
> -    AVIOContext *pb = s->pb;
> +    ASFContext *asf  = s->priv_data;
> +    AVIOContext *pb  = s->pb;
> +    uint64_t size    = avio_rl64(pb);
> +    uint16_t nb_desc = avio_rl16(pb);
> +    int i, ret;
>  
> -    ff_get_guid(pb, &asf->hdr.guid);
> -    asf->hdr.file_size   = avio_rl64(pb);
> -    asf->hdr.create_time = avio_rl64(pb);
> -    avio_rl64(pb);                               /* number of packets */
> -    asf->hdr.play_time   = avio_rl64(pb);
> -    asf->hdr.send_time   = avio_rl64(pb);
> -    asf->hdr.preroll     = avio_rl32(pb);
> -    asf->hdr.ignore      = avio_rl32(pb);
> -    asf->hdr.flags       = avio_rl32(pb);
> -    asf->hdr.min_pktsize = avio_rl32(pb);
> -    asf->hdr.max_pktsize = avio_rl32(pb);
> -    if (asf->hdr.min_pktsize >= (1U << 29))
> -        return AVERROR_INVALIDDATA;
> -    asf->hdr.max_bitrate = avio_rl32(pb);
> -    s->packet_size       = asf->hdr.max_pktsize;
> +    for (i = 0; i < nb_desc; i++) {
> +        uint16_t name_len, type, val_len;
> +        uint8_t *name = NULL;
>  
> +        name_len = avio_rl16(pb);
> +        if (!name_len)
> +            return AVERROR_INVALIDDATA;
> +        name = av_malloc(name_len);
> +        if (!name)
> +            return AVERROR(ENOMEM);
> +        avio_get_str16le(pb, name_len, name,
> +                         name_len);
> +        type    = avio_rl16(pb);
> +        val_len = avio_rl16(pb);
> +
> +        if ((ret = process_metadata(s, name, val_len, type, &s->metadata)) < 
> 0)
> +            return ret;
> +    }
> +
> +    align_position(pb, asf->offset, size);
>      return 0;
>  }
>  
> -static int asf_read_stream_properties(AVFormatContext *s, int64_t size)
> +static AVStream *find_stream(AVFormatContext *s, ASFContext *asf, uint16_t 
> st_num)
>  {
> -    ASFContext *asf = s->priv_data;
> -    AVIOContext *pb = s->pb;
> -    AVStream *st;
> -    ASFStream *asf_st;
> -    ff_asf_guid g;
> -    enum AVMediaType type;
> -    int type_specific_size, sizeX;
> -    unsigned int tag1;
> -    int64_t pos1, pos2, start_time;
> -    int test_for_ext_stream_audio, is_dvr_ms_audio = 0;
> -
> -    if (s->nb_streams == ASF_MAX_STREAMS) {
> -        av_log(s, AV_LOG_ERROR, "too many streams\n");
> -        return AVERROR(EINVAL);
> -    }
> -
> -    pos1 = avio_tell(pb);
> -
> -    st = avformat_new_stream(s, NULL);
> -    if (!st)
> -        return AVERROR(ENOMEM);
> -    avpriv_set_pts_info(st, 32, 1, 1000); /* 32 bit pts in ms */
> -    asf_st = av_mallocz(sizeof(ASFStream));
> -    if (!asf_st)
> -        return AVERROR(ENOMEM);
> -    st->priv_data  = asf_st;
> -    st->start_time = 0;
> -    start_time     = asf->hdr.preroll;
> -
> -    asf_st->stream_language_index = 128; // invalid stream index means no 
> language info
> -
> -    if (!(asf->hdr.flags & 0x01)) { // if we aren't streaming...
> -        st->duration = asf->hdr.play_time /
> -                       (10000000 / 1000) - start_time;
> -    }
> -    ff_get_guid(pb, &g);
> +    AVStream *st = NULL;
> +    int i;
>  
> -    test_for_ext_stream_audio = 0;
> -    if (!ff_guidcmp(&g, &ff_asf_audio_stream)) {
> -        type = AVMEDIA_TYPE_AUDIO;
> -    } else if (!ff_guidcmp(&g, &ff_asf_video_stream)) {
> -        type = AVMEDIA_TYPE_VIDEO;
> -    } else if (!ff_guidcmp(&g, &ff_asf_jfif_media)) {
> -        type                = AVMEDIA_TYPE_VIDEO;
> -        st->codec->codec_id = AV_CODEC_ID_MJPEG;
> -    } else if (!ff_guidcmp(&g, &ff_asf_command_stream)) {
> -        type = AVMEDIA_TYPE_DATA;
> -    } else if (!ff_guidcmp(&g, &ff_asf_ext_stream_embed_stream_header)) {
> -        test_for_ext_stream_audio = 1;
> -        type                      = AVMEDIA_TYPE_UNKNOWN;
> -    } else {
> -        return -1;
> -    }
> -    ff_get_guid(pb, &g);
> -    avio_skip(pb, 8); /* total_size */
> -    type_specific_size = avio_rl32(pb);
> -    avio_rl32(pb);
> -    st->id = avio_rl16(pb) & 0x7f; /* stream id */
> -    // mapping of asf ID to AV stream ID;
> -    asf->asfid2avid[st->id] = s->nb_streams - 1;
> -
> -    avio_rl32(pb);
> -
> -    if (test_for_ext_stream_audio) {
> -        ff_get_guid(pb, &g);
> -        if (!ff_guidcmp(&g, &ff_asf_ext_stream_audio_stream)) {
> -            type            = AVMEDIA_TYPE_AUDIO;
> -            is_dvr_ms_audio = 1;
> -            ff_get_guid(pb, &g);
> -            avio_rl32(pb);
> -            avio_rl32(pb);
> -            avio_rl32(pb);
> -            ff_get_guid(pb, &g);
> -            avio_rl32(pb);
> +    for (i = 0; i < asf->nb_streams; i++) {
> +        if (asf->asf_st[i]->stream_index == st_num) {
> +            st = s->streams[asf->asf_st[i]->index];
> +            break;
>          }
>      }
>  
> -    st->codec->codec_type = type;
> -    if (type == AVMEDIA_TYPE_AUDIO) {
> -        int ret = ff_get_wav_header(pb, st->codec, type_specific_size);
> -        if (ret < 0)
> -            return ret;
> -        if (is_dvr_ms_audio) {
> -            // codec_id and codec_tag are unreliable in dvr_ms
> -            // files. Set them later by probing stream.
> -            st->codec->codec_id  = AV_CODEC_ID_PROBE;
> -            st->codec->codec_tag = 0;
> -        }
> -        if (st->codec->codec_id == AV_CODEC_ID_AAC)
> -            st->need_parsing = AVSTREAM_PARSE_NONE;
> -        else
> -            st->need_parsing = AVSTREAM_PARSE_FULL;
> -        /* We have to init the frame size at some point .... */
> -        pos2 = avio_tell(pb);
> -        if (size >= (pos2 + 8 - pos1 + 24)) {
> -            asf_st->ds_span        = avio_r8(pb);
> -            asf_st->ds_packet_size = avio_rl16(pb);
> -            asf_st->ds_chunk_size  = avio_rl16(pb);
> -            avio_rl16(pb);  // ds_data_size
> -            avio_r8(pb);    // ds_silence_data
> -        }
> -        if (asf_st->ds_span > 1) {
> -            if (!asf_st->ds_chunk_size                                ||
> -                (asf_st->ds_packet_size / asf_st->ds_chunk_size <= 1) ||
> -                asf_st->ds_packet_size % asf_st->ds_chunk_size)
> -                asf_st->ds_span = 0;  // disable descrambling
> -        }
> -    } else if (type == AVMEDIA_TYPE_VIDEO &&
> -               size - (avio_tell(pb) - pos1 + 24) >= 51) {
> -        avio_rl32(pb);
> -        avio_rl32(pb);
> -        avio_r8(pb);
> -        avio_rl16(pb);        /* size */
> -        sizeX             = avio_rl32(pb); /* size */
> -        st->codec->width  = avio_rl32(pb);
> -        st->codec->height = avio_rl32(pb);
> -        /* not available for asf */
> -        avio_rl16(pb); /* panes */
> -        st->codec->bits_per_coded_sample = avio_rl16(pb); /* depth */
> -        tag1                             = avio_rl32(pb);
> -        avio_skip(pb, 20);
> -        if (sizeX > 40) {
> -            st->codec->extradata_size = sizeX - 40;
> -            st->codec->extradata      = av_mallocz(st->codec->extradata_size 
> +
> -                                                   
> FF_INPUT_BUFFER_PADDING_SIZE);
> -            avio_read(pb, st->codec->extradata, st->codec->extradata_size);
> -        }
> -
> -        /* Extract palette from extradata if bpp <= 8 */
> -        /* This code assumes that extradata contains only palette */
> -        /* This is true for all paletted codecs implemented in libavcodec */
> -        if (st->codec->extradata_size && (st->codec->bits_per_coded_sample 
> <= 8)) {
> -#if HAVE_BIGENDIAN
> -            int i;
> -            for (i = 0; i < FFMIN(st->codec->extradata_size, AVPALETTE_SIZE) 
> / 4; i++)
> -                asf_st->palette[i] = av_bswap32(((uint32_t 
> *)st->codec->extradata)[i]);
> -#else
> -            memcpy(asf_st->palette, st->codec->extradata,
> -                   FFMIN(st->codec->extradata_size, AVPALETTE_SIZE));
> -#endif
> -            asf_st->palette_changed = 1;
> -        }
> +    return st;
> +}
>  
> -        st->codec->codec_tag = tag1;
> -        st->codec->codec_id  = ff_codec_get_id(ff_codec_bmp_tags, tag1);
> -        if (tag1 == MKTAG('D', 'V', 'R', ' ')) {
> -            st->need_parsing = AVSTREAM_PARSE_FULL;
> -            /* issue658 contains wrong w/h and MS even puts a fake seq header
> -             * with wrong w/h in extradata while a correct one is in the 
> stream.
> -             * maximum lameness */
> -            st->codec->width      =
> -                st->codec->height = 0;
> -            av_freep(&st->codec->extradata);
> -            st->codec->extradata_size = 0;
> +static int asf_read_metadata_obj(AVFormatContext *s, const GUIDParseTable *g)
> +{
> +    ASFContext *asf   = s->priv_data;
> +    AVIOContext *pb   = s->pb;
> +    AVDictionary **met = NULL;
> +    uint64_t size     = avio_rl64(pb);
> +    uint16_t nb_recs  = avio_rl16(pb); // number of records in the 
> Description Records list
> +    AVStream *st      = NULL;
> +    int i, ret;
> +
> +    for (i = 0; i < nb_recs; i++) {
> +        uint16_t name_len, buflen, type, val_len, st_num = 0;
> +        uint8_t *name = NULL;
> +
> +        avio_skip(pb, 2); // skip reserved field
> +        st_num   = avio_rl16(pb);
> +        name_len = avio_rl16(pb);
> +        buflen   = 2 * name_len + 1;
> +        if (!name_len)
> +            break;
> +        type     = avio_rl16(pb);
> +        val_len  = avio_rl32(pb);
> +        name     = av_malloc(name_len);
> +        if (!name)
> +            return AVERROR(ENOMEM);
> +        avio_get_str16le(pb, name_len, name,
> +                         buflen);
> +        find_stream(s, asf, st_num);

Seriously? How about actually testing this stuff once in a while.
Also, this won't work if this object is stored before the streams
properties.

> +        if (st)
> +            met = &st->metadata;
> +        else {
> +            av_log(s, AV_LOG_WARNING, "Can't find matching stream for the 
> processed "
> +            "metadata"".\n");
> +            met = &s->metadata;
>          }
> -        if (st->codec->codec_id == AV_CODEC_ID_H264)
> -            st->need_parsing = AVSTREAM_PARSE_FULL_ONCE;
> +        if ((ret = process_metadata(s, name, val_len, type, met)) < 0)
> +            break;
>      }
> -    pos2 = avio_tell(pb);
> -    avio_skip(pb, size - (pos2 - pos1 + 24));
>  
> +    align_position(pb, asf->offset, size);
>      return 0;
>  }
>  
> -static int asf_read_ext_stream_properties(AVFormatContext *s, int64_t size)
> +static int asf_read_content_desc(AVFormatContext *s, const GUIDParseTable *g)
>  {
>      ASFContext *asf = s->priv_data;
>      AVIOContext *pb = s->pb;
> -    ff_asf_guid g;
> -    int ext_len, payload_ext_ct, stream_ct, i;
> -    uint32_t leak_rate, stream_num;
> -    unsigned int stream_languageid_index;
> -
> -    avio_rl64(pb); // starttime
> -    avio_rl64(pb); // endtime
> -    leak_rate = avio_rl32(pb); // leak-datarate
> -    avio_rl32(pb); // bucket-datasize
> -    avio_rl32(pb); // init-bucket-fullness
> -    avio_rl32(pb); // alt-leak-datarate
> -    avio_rl32(pb); // alt-bucket-datasize
> -    avio_rl32(pb); // alt-init-bucket-fullness
> -    avio_rl32(pb); // max-object-size
> -    avio_rl32(pb); // flags 
> (reliable,seekable,no_cleanpoints?,resend-live-cleanpoints, rest of bits 
> reserved)
> -    stream_num = avio_rl16(pb); // stream-num
> -
> -    stream_languageid_index = avio_rl16(pb); // stream-language-id-index
> -    if (stream_num < 128)
> -        asf->streams[stream_num].stream_language_index = 
> stream_languageid_index;
> -
> -    avio_rl64(pb); // avg frametime in 100ns units
> -    stream_ct      = avio_rl16(pb); // stream-name-count
> -    payload_ext_ct = avio_rl16(pb); // payload-extension-system-count
> -
> -    if (stream_num < 128)
> -        asf->stream_bitrates[stream_num] = leak_rate;
> -
> -    for (i = 0; i < stream_ct; i++) {
> -        avio_rl16(pb);
> -        ext_len = avio_rl16(pb);
> -        avio_skip(pb, ext_len);
> +    int i;
> +    static const char *const titles[] =
> +    { "Title", "Author", "Copyright", "Description", "Rate" };
> +    uint16_t len[5], buflen = 0;
> +    uint8_t *ch;
> +    uint64_t size = avio_rl64(pb);
> +
> +    for (i = 0; i < 5; i++) {
> +        len[i]  = avio_rl16(pb);
> +        // utf8 string should be <= 2 * utf16 string, extra byte for the 
> terminator
> +        buflen  = 2 * len[i] + 1;

This does not look right.

>      }
> -
> -    for (i = 0; i < payload_ext_ct; i++) {
> -        ff_get_guid(pb, &g);
> -        avio_skip(pb, 2);
> -        ext_len = avio_rl32(pb);
> -        avio_skip(pb, ext_len);
> +    if (buflen) {

Can buflen actually be zero?

> +        ch = av_malloc(sizeof(buflen));

sizeof?

> +        if (!ch)
> +            return(AVERROR(ENOMEM));
> +        for (i = 0; i < 5; i++)
> +            asf_read_metadata(s, titles[i], len[i], ch, buflen);
> +        av_freep(&ch);
>      }
> +    align_position(pb, asf->offset, size);
>  
>      return 0;
>  }
>  
> -static int asf_read_content_desc(AVFormatContext *s, int64_t size)
> +static int asf_read_properties(AVFormatContext *s, const GUIDParseTable *g)
>  {
> +    ASFContext *asf = s->priv_data;
>      AVIOContext *pb = s->pb;
> -    int len1, len2, len3, len4, len5;
> -
> -    len1 = avio_rl16(pb);
> -    len2 = avio_rl16(pb);
> -    len3 = avio_rl16(pb);
> -    len4 = avio_rl16(pb);
> -    len5 = avio_rl16(pb);
> -    get_tag(s, "title", 0, len1, 32);
> -    get_tag(s, "author", 0, len2, 32);
> -    get_tag(s, "copyright", 0, len3, 32);
> -    get_tag(s, "comment", 0, len4, 32);
> -    avio_skip(pb, len5);
> +    uint64_t creation_time;
> +    struct tm tmbuf;
> +    struct tm *tm;
> +    char buf[64] = {0};

Those variables should be moved into the block where they are used. And
there does not seem to be any need to zero all of buf.

> +static int asf_read_ext_stream_properties(AVFormatContext *s, const 
> GUIDParseTable *g)
>  {
> -    AVIOContext *pb = s->pb;
>      ASFContext *asf = s->priv_data;
> -    int j, ret;
> -    int stream_count = avio_rl16(pb);
> -    for (j = 0; j < stream_count; j++) {
> -        char lang[6];
> -        unsigned int lang_len = avio_r8(pb);
> -        if ((ret = avio_get_str16le(pb, lang_len, lang,
> -                                    sizeof(lang))) < lang_len)
> -            avio_skip(pb, lang_len - ret);
> -        if (j < 128)
> -            av_strlcpy(asf->stream_languages[j], lang,
> -                       sizeof(*asf->stream_languages));
> +    AVIOContext *pb = s->pb;
> +    AVStream *st    = NULL;
> +    ff_asf_guid guid;
> +    uint16_t nb_st_name, nb_pay_exts, st_num, lang_idx;
> +    int i, ret;
> +    uint32_t bitrate;
> +    uint64_t start_time, end_time, time_per_frame;
> +    uint64_t size = avio_rl64(pb);
> +
> +    start_time = avio_rl64(pb);
> +    end_time   = avio_rl64(pb);
> +    bitrate    = avio_rl32(pb);
> +    avio_skip(pb, 28); // skip some unused values
> +    st_num     = avio_rl16(pb);
> +    st_num    &= ASF_STREAM_NUM;
> +    lang_idx   = avio_rl16(pb); // Stream Language ID Index
> +    for (i = 0; i < asf->nb_streams; i++) {
> +        if (st_num == asf->asf_st[i]->stream_index) {
> +            st                       = s->streams[asf->asf_st[i]->index];
> +            asf->asf_st[i]->lang_idx = lang_idx;
> +            break;
> +        }
> +    }
> +    time_per_frame = avio_rl64(pb); // average time per frame
> +    if (st) {
> +        st->start_time           = start_time;
> +        st->duration             = end_time - start_time;
> +        st->codec->bit_rate      = bitrate;
> +        st->avg_frame_rate.num   = 10000000;
> +        st->avg_frame_rate.den   = time_per_frame;
> +    }
> +    nb_st_name = avio_rl16(pb);
> +    nb_pay_exts   = avio_rl16(pb);
> +    for (i = 0; i < nb_st_name; i++) {
> +        uint16_t len;
> +
> +        avio_rl16(pb); // Language ID Index
> +        len = avio_rl16(pb);
> +        avio_skip(pb, len);
> +    }
> +
> +    for (i = 0; i < nb_pay_exts; i++) {
> +        uint32_t len;
> +        avio_skip(pb, 16); // Extension System ID
> +        avio_skip(pb, 2);  // Extension Data Size
> +        len = avio_rl32(pb);
> +        avio_skip(pb, len);
>      }
>  
> +    if ((ret = ff_get_guid(pb, &guid)) < 0) {
> +        align_position(pb, asf->offset, size);
> +
> +        return 0;
> +    }
> +
> +    g = find_guid(guid);
> +    if (g && !(strcmp(g->name, "Stream Properties"))) {

Will this actually work? Because it seems to me it will fail horribly.

> +        if ((ret = g->read_object(s, g)) < 0)
> +            return ret;
> +    }
> +
> +    align_position(pb, asf->offset, size);
>      return 0;
>  }
>  
> -static int asf_read_metadata(AVFormatContext *s, int64_t size)
> +static int asf_read_language_list(AVFormatContext *s, const GUIDParseTable 
> *g)
>  {
> -    AVIOContext *pb = s->pb;
> -    ASFContext *asf = s->priv_data;
> -    int n, stream_num, name_len, value_len;
> -    int ret, i;
> -    n = avio_rl16(pb);
> -
> -    for (i = 0; i < n; i++) {
> -        char name[1024];
> -        int value_type;
> -
> -        avio_rl16(pb);  // lang_list_index
> -        stream_num = avio_rl16(pb);
> -        name_len   = avio_rl16(pb);
> -        value_type = avio_rl16(pb); /* value_type */
> -        value_len  = avio_rl32(pb);
> -
> -        if ((ret = avio_get_str16le(pb, name_len, name, sizeof(name))) < 
> name_len)
> -            avio_skip(pb, name_len - ret);
> -        av_dlog(s, "%d stream %d name_len %2d type %d len %4d <%s>\n",
> -                i, stream_num, name_len, value_type, value_len, name);
> -
> -        if (!strcmp(name, "AspectRatioX")){
> -            int aspect_x = get_value(s->pb, value_type, 16);
> -            if(stream_num < 128)
> -                asf->dar[stream_num].num = aspect_x;
> -        } else if(!strcmp(name, "AspectRatioY")){
> -            int aspect_y = get_value(s->pb, value_type, 16);
> -            if(stream_num < 128)
> -                asf->dar[stream_num].den = aspect_y;
> -        } else {
> -            get_tag(s, name, value_type, value_len, 16);
> +    ASFContext *asf   = s->priv_data;
> +    AVIOContext *pb   = s->pb;
> +    int i, ret;
> +    uint64_t size     = avio_rl64(pb);
> +    uint16_t nb_langs = avio_rl16(pb);
> +
> +    for (i = 0; i < nb_langs; i++) {
> +        size_t len;
> +        len = avio_r8(pb);
> +        if (!len)
> +            len = 6;
> +        // len is number of unicode characters - 2 bytes for each char

The comment does not match the code -- one of them is probably wrong.

> +static int asf_read_header(AVFormatContext *s)
> +{
> +    ASFContext *asf         = s->priv_data;
> +    AVIOContext *pb         = s->pb;
> +    const GUIDParseTable *g = NULL;
> +    ff_asf_guid guid;
> +    int i, ret;
> +    uint64_t size;
> +
> +    asf->preroll         = 0;
> +    asf->is_simple_index = 0;
> +    ff_get_guid(pb, &guid);
> +    if (ff_guidcmp(&guid, &ff_asf_header))
> +        return AVERROR_INVALIDDATA;
> +    asf->header_obj_size = avio_rl64(pb);
> +    avio_skip(pb, 6); // skip number of header objects and 2 reserved bytes
> +    asf->data_reached = 0;
> +
> +    // 1  is here instead of pb->eof_reached because, Data are skipped for 
> the first time,
> +    // Index object is processed and got eof and then seeking back to the 
> Data is performed.
> +    while (1) {
> +        asf->offset = avio_tell(pb);
> +        if (asf->offset > asf->header_obj_size && !asf->data_reached) {
> +            avio_seek(pb, asf->header_obj_size, SEEK_SET);
> +            asf->offset = asf->header_obj_size;

Won't this cause an inifinet loop if there's no data object in the file?
I believe I already asked this once without an answer.

>          }
> +        if ((ret = ff_get_guid(pb, &guid)) < 0) {
> +            if (ret == AVERROR_EOF && asf->data_reached) {
> +                avio_seek(pb, asf->first_packet_offset, SEEK_SET);
> +                break;
> +            } else
> +                return ret;
> +        }
> +        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;
> +        } else {
> +            size = avio_rl64(pb);
> +            align_position(pb, asf->offset, size);
> +        }
> +        if (asf->data_reached || !pb->seekable)

So, if it breaks immediately after data is reached, when does the index
get read?

-- 
Anton Khirnov

_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to