Hi,
For my application a need to know the file duration, and to timestamp
packets so I can seek...
I first read FLAC documentation and so I learn that FLAC have a variable
bitrate and frame are not timestamped :s
then I took a look at mplayer to see how they manage to have elapsed
time / duration / seek...
I discovered that they evaluate an average bitrate and they use it as if
it was a constant bitrate.
So I made the same for libavformat.
I modified libavformat/raw.c with a specific read_header() for flac.
this read_header evaluate the average bitrate.
and with the bitrate information available, duration and timestamp are
processed for each packet!
This evaluation can be far away from truth for specific kind of
signals... but for most of normal songs it will works just fine :)
I join a patch if it can help!
NB : I think it should be better in ffmpeg-devel mailing list, but I
don't have acces to it...
diff -cr ffmpeg-export-2008-10-10/libavformat/raw.c ffmpeg-export-2008-10-10_modif/libavformat/raw.c
*** ffmpeg-export-2008-10-10/libavformat/raw.c 2008-10-03 12:16:29.000000000 +0200
--- ffmpeg-export-2008-10-10_modif/libavformat/raw.c 2008-11-18 17:03:46.000000000 +0100
***************
*** 563,568 ****
--- 563,608 ----
if(memcmp(p->buf, "fLaC", 4)) return 0;
else return AVPROBE_SCORE_MAX / 2;
}
+
+ static int flac_read_header(AVFormatContext *s, AVFormatParameters *ap)
+ {
+ uint32_t dataRead;
+ uint64_t nbSamples;
+ ByteIOContext *pb = s->pb;
+ AVStream *st = av_new_stream(s, 0);
+ if (!st)
+ return AVERROR(ENOMEM);
+ st->codec->codec_type = CODEC_TYPE_AUDIO;
+ st->codec->codec_id = s->iformat->value;
+ st->need_parsing = AVSTREAM_PARSE_FULL;
+
+ //evaluate bit_rate from sample rate, number of samples and file size
+ //without this bit_rate we cannot evaluate any duration and/or timestamps, see note below about accuracy problems
+ url_fseek(pb, 0, SEEK_SET);
+ dataRead = get_le32(pb);
+ if (dataRead != MKTAG('f', 'L', 'a', 'C')){
+ return -1;
+ }
+
+ //extract Sample Rate from file header
+ url_fseek(pb, 18, SEEK_SET);
+ dataRead = get_be32(pb);
+ st->codec->sample_rate = (dataRead>>12) & 0x00ffffff;
+
+ //extract number of samples from file header
+ nbSamples = (dataRead<<32) & 0x0000000f00000000;
+ dataRead = get_be32(pb);
+ nbSamples |= dataRead & 0x00000000ffffffff; //maybe useless mask, but better anticipate some exotic compilers...
+
+ //then average bitrate is (fileSize * sample_rate / nbSamples)
+ //!! Note that this is an AVERAGE bitrate because flac don't have a fixed bitrate
+ //!! So if we use it to calculate timestamp and/or packet duration values will only be estimations and can be far away from truth on specific audio files, but on most of songs it will work so it's better than nothing
+ st->codec->bit_rate = 8 * url_fsize(pb) * st->codec->sample_rate / nbSamples;
+
+ url_fseek(pb, 0, SEEK_SET); //we need to go back to the begining for the first read packet to detect the frame header
+ /* other parameters will be extracted from the compressed bitstream */
+ return 0;
+ }
#endif
***************
*** 703,709 ****
NULL_IF_CONFIG_SMALL("raw FLAC"),
0,
flac_probe,
! audio_read_header,
raw_read_partial_packet,
.flags= AVFMT_GENERIC_INDEX,
.extensions = "flac",
--- 743,749 ----
NULL_IF_CONFIG_SMALL("raw FLAC"),
0,
flac_probe,
! flac_read_header,
raw_read_partial_packet,
.flags= AVFMT_GENERIC_INDEX,
.extensions = "flac",
_______________________________________________
libav-user mailing list
[email protected]
https://lists.mplayerhq.hu/mailman/listinfo/libav-user