Merge commit 'ed1cd81076434b76f37576d4d806973476a8e96c'
authorClément Bœsch <u@pkh.me>
Wed, 15 Mar 2017 22:16:23 +0000 (23:16 +0100)
committerClément Bœsch <u@pkh.me>
Wed, 15 Mar 2017 22:17:32 +0000 (23:17 +0100)
* commit 'ed1cd81076434b76f37576d4d806973476a8e96c':
  flac demuxer: improve probing

Suggested commit very closely matches our code, except with regards to
AVPROBE_SCORE_EXTENSION. The code layout is mostly merged but preserves
our behaviour.

Merged-by: Clément Bœsch <u@pkh.me>
1  2 
libavformat/flacdec.c

@@@ -229,93 -177,26 +229,104 @@@ static int raw_flac_probe(AVProbeData *
  
  static int flac_probe(AVProbeData *p)
  {
-     if (p->buf_size < 4 || memcmp(p->buf, "fLaC", 4))
-         return 0;
-     if (   p->buf[4] & 0x7f != FLAC_METADATA_TYPE_STREAMINFO
-         || AV_RB24(p->buf + 5) != FLAC_STREAMINFO_SIZE
-         || AV_RB16(p->buf + 8) < 16
-         || AV_RB16(p->buf + 8) > AV_RB16(p->buf + 10)
-         || !(AV_RB24(p->buf + 18) >> 4)
-         || AV_RB24(p->buf + 18) >> 4 > 655350)
 +    if ((AV_RB16(p->buf) & 0xFFFE) == 0xFFF8)
 +        return raw_flac_probe(p);
 -        if (!memcmp(p->buf, "fLaC", 4)            &&
 -            type == FLAC_METADATA_TYPE_STREAMINFO &&
++
+     /* file header + metadata header + checked bytes of streaminfo */
+     if (p->buf_size >= 4 + 4 + 13) {
+         int type           = p->buf[4] & 0x7f;
+         int size           = AV_RB24(p->buf + 5);
+         int min_block_size = AV_RB16(p->buf + 8);
+         int max_block_size = AV_RB16(p->buf + 10);
+         int sample_rate    = AV_RB24(p->buf + 18) >> 4;
-     return AVPROBE_SCORE_MAX;
++        if (memcmp(p->buf, "fLaC", 4))
++            return 0;
++        if (type == FLAC_METADATA_TYPE_STREAMINFO &&
+             size == FLAC_STREAMINFO_SIZE          &&
+             min_block_size >= 16                  &&
+             max_block_size >= min_block_size      &&
+             sample_rate && sample_rate <= 655350)
+             return AVPROBE_SCORE_MAX;
 +        return AVPROBE_SCORE_EXTENSION;
+     }
+     return 0;
  }
  
 +static av_unused int64_t flac_read_timestamp(AVFormatContext *s, int stream_index,
 +                                             int64_t *ppos, int64_t pos_limit)
 +{
 +    AVPacket pkt, out_pkt;
 +    AVStream *st = s->streams[stream_index];
 +    AVCodecParserContext *parser;
 +    int ret;
 +    int64_t pts = AV_NOPTS_VALUE;
 +
 +    if (avio_seek(s->pb, *ppos, SEEK_SET) < 0)
 +        return AV_NOPTS_VALUE;
 +
 +    av_init_packet(&pkt);
 +    parser = av_parser_init(st->codecpar->codec_id);
 +    if (!parser){
 +        return AV_NOPTS_VALUE;
 +    }
 +    parser->flags |= PARSER_FLAG_USE_CODEC_TS;
 +
 +    for (;;){
 +        ret = ff_raw_read_partial_packet(s, &pkt);
 +        if (ret < 0){
 +            if (ret == AVERROR(EAGAIN))
 +                continue;
 +            else {
 +                av_packet_unref(&pkt);
 +                av_assert1(!pkt.size);
 +            }
 +        }
 +        av_init_packet(&out_pkt);
 +        av_parser_parse2(parser, st->internal->avctx,
 +                         &out_pkt.data, &out_pkt.size, pkt.data, pkt.size,
 +                         pkt.pts, pkt.dts, *ppos);
 +
 +        av_packet_unref(&pkt);
 +        if (out_pkt.size){
 +            int size = out_pkt.size;
 +            if (parser->pts != AV_NOPTS_VALUE){
 +                // seeking may not have started from beginning of a frame
 +                // calculate frame start position from next frame backwards
 +                *ppos = parser->next_frame_offset - size;
 +                pts = parser->pts;
 +                break;
 +            }
 +        } else if (ret < 0)
 +            break;
 +    }
 +    av_parser_close(parser);
 +    return pts;
 +}
 +
 +static int flac_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags) {
 +    int index;
 +    int64_t pos;
 +    AVIndexEntry e;
 +    FLACDecContext *flac = s->priv_data;
 +
 +    if (!flac->found_seektable || !(s->flags&AVFMT_FLAG_FAST_SEEK)) {
 +        return -1;
 +    }
 +
 +    index = av_index_search_timestamp(s->streams[0], timestamp, flags);
 +    if(index<0 || index >= s->streams[0]->nb_index_entries)
 +        return -1;
 +
 +    e = s->streams[0]->index_entries[index];
 +    pos = avio_seek(s->pb, e.pos, SEEK_SET);
 +    if (pos >= 0) {
 +        return 0;
 +    }
 +    return -1;
 +}
 +
  AVInputFormat ff_flac_demuxer = {
      .name           = "flac",
      .long_name      = NULL_IF_CONFIG_SMALL("raw FLAC"),