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"),