Quoting Alexandra Hájková (2015-04-17 12:34:13)
>  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;

I already asked in the last review -- any reason for this to be signed?
Also, is this variable even needed?

> +static int asf_read_value(AVFormatContext *s, uint8_t *name, uint16_t 
> name_len,
> +                          uint16_t val_len, int type, AVDictionary **met)
> +{
> +    int ret;
> +    uint8_t *value;
> +    uint16_t buflen = 2 * val_len + 1;
> +    AVIOContext *pb = s->pb;
> +
> +    value = av_malloc(buflen);
> +    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) {
> +            av_freep(&value);

What part of 'same below' in the last review was unclear?

> -    asf_st->stream_language_index = 128; // invalid stream index means no 
> language info
> +static int asf_read_metadata_obj(AVFormatContext *s, const GUIDParseTable *g)
> +{
> +    ASFContext *asf   = s->priv_data;
> +    AVIOContext *pb   = s->pb;
> +    uint64_t size     = avio_rl64(pb);
> +    uint16_t nb_recs  = avio_rl16(pb); // number of records in the 
> Description Records list
> +    int i, ret;
>  
> -    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);
> +    for (i = 0; i < nb_recs; i++) {
> +        uint16_t name_len, buflen, type, val_len, st_num;
> +        uint8_t *name = NULL;
>  
> -    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);
> -        }
> +        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);
> +        if ((ret = process_metadata(s, name, name_len, val_len, type, 
> &asf->asf_met[st_num])) < 0)

st_num is a 16-bit number, so this is a potential invalid write

> +static int asf_read_content_desc(AVFormatContext *s, const GUIDParseTable *g)
> +{
> +    ASFContext *asf = s->priv_data;
> +    AVIOContext *pb = s->pb;
> +    int i;
> +    static const char *const titles[] =
> +    { "Title", "Author", "Copyright", "Description", "Rate" };
> +    uint16_t len[5], buflen[5] = {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[i]  = 2 * len[i] + 1;
> +    }
>  
> -        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;
> +    for (i = 0; i < 5; i++) {
> +        if (buflen[i]) {

Can buflen be zero?

> +static int asf_read_properties(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);
> -    }
> -
> -    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);
> +    uint64_t creation_time;
> +
> +    avio_rl64(pb); // read object size
> +    avio_skip(pb, 16); // skip File ID
> +    avio_skip(pb, 8);  // skip File size
> +    creation_time = avio_rl64(pb);
> +    if (!(asf->b_flags & ASF_FLAG_BROADCAST)) {
> +        struct tm tmbuf;
> +        struct tm *tm;
> +        char buf[64] = {0};

As I already said last time, there does not seem to be any need to
initialize buf.

> +// returns data object offset when reading this object for the first time
> +static int asf_read_data(AVFormatContext *s, const GUIDParseTable *g)
>  {
> -    AVIOContext *pb = s->pb;
>      ASFContext *asf = s->priv_data;
> -    int i, count, name_len, ret;
> -    char name[1024];
> +    AVIOContext *pb = s->pb;
> +    uint64_t size   = asf->data_size = avio_rl64(pb);
> +    int i;
>  
> -    avio_rl64(pb);            // reserved 16 bytes
> -    avio_rl64(pb);            // ...
> -    count = avio_rl32(pb);    // markers count
> -    avio_rl16(pb);            // reserved 2 bytes
> -    name_len = avio_rl16(pb); // name length
> -    for (i = 0; i < name_len; i++)
> -        avio_r8(pb); // skip the name
> -
> -    for (i = 0; i < count; i++) {
> -        int64_t pres_time;
> -        int name_len;
> -
> -        avio_rl64(pb);             // offset, 8 bytes
> -        pres_time = avio_rl64(pb); // presentation time
> -        pres_time -= asf->hdr.preroll * 10000;
> -        avio_rl16(pb);             // entry length
> -        avio_rl32(pb);             // send time
> -        avio_rl32(pb);             // flags
> -        name_len = avio_rl32(pb);  // name length
> -        if ((ret = avio_get_str16le(pb, name_len * 2, name,
> -                                    sizeof(name))) < name_len)
> -            avio_skip(pb, name_len - ret);
> -        avpriv_new_chapter(s, i, (AVRational) { 1, 10000000 }, pres_time,
> -                           AV_NOPTS_VALUE, name);
> +    if (!asf->data_reached && pb->seekable) {
> +        asf->data_reached       = 1;
> +        asf->data_offset  = asf->offset;
>      }
>  
> +    if (!(asf->b_flags & ASF_FLAG_BROADCAST) && !s->streams[i]->duration) {

What is the value of i here?

> +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.

So, when exactly does the index get read?
And again, I asked this already in the last review.

> +    while (1) {
> +        if (avio_tell(pb) == asf->offset) {
> +            if (asf->data_reached)
> +                avio_seek(pb, asf->first_packet_offset, SEEK_SET);
> +            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);
> +                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)
> +            break;
>      }
>  
> -    if (!asf->index_read)
> -        ret = asf_build_simple_index(s, stream_index);
> +    for (i = 0; i < asf->nb_streams; i++) {
> +        const char *rfc1766 = asf->langs[asf->asf_st[i]->lang_idx];
> +        AVStream *st        = s->streams[asf->asf_st[i]->index];
> +        set_language(s, rfc1766, &st->metadata);
> +    }
>  
> -    if (!ret && asf->index_read && st->index_entries) {
> -        index = av_index_search_timestamp(st, pts, flags);
> -        if (index >= 0) {
> -            /* find the position */
> -            pos = st->index_entries[index].pos;
> +    for (i = 0; i < ASF_MAX_STREAMS; i++) {
> +        AVStream *st = NULL;
>  
> -            /* do the seek */
> -            av_log(s, AV_LOG_DEBUG, "SEEKTO: %"PRId64"\n", pos);
> -            avio_seek(s->pb, pos, SEEK_SET);
> -            asf_reset_header(s);
> -            return 0;
> -        }
> +        st = find_stream(s, i);
> +        if (st)
> +            av_dict_copy(&st->metadata, asf->asf_met[i], 
> AV_DICT_IGNORE_SUFFIX);
>      }
> -    /* no index or seeking by index failed */
> -    if (ff_seek_frame_binary(s, stream_index, pts, flags) < 0)
> -        return -1;
> -    asf_reset_header(s);
> +
>      return 0;
> +

Extra empty line.

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

Reply via email to