[FFmpeg-devel] [PATCH 05/28] support seeking in nuv files
Reimar Döffinger
Reimar.Doeffinger
Wed Jun 30 19:22:59 CEST 2010
On Wed, Jun 30, 2010 at 10:09:33AM +0100, Mans Rullgard wrote:
> From: Cory Fields <theuni-nospam- at xbmc.org>
>
> ---
> libavformat/nuv.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++++
> 1 files changed, 84 insertions(+), 0 deletions(-)
>
> diff --git a/libavformat/nuv.c b/libavformat/nuv.c
> index f0eacd5..2aa0bb4 100644
> --- a/libavformat/nuv.c
> +++ b/libavformat/nuv.c
> @@ -218,12 +218,18 @@ static int nuv_packet(AVFormatContext *s, AVPacket *pkt) {
> ret = av_new_packet(pkt, copyhdrsize + size);
> if (ret < 0)
> return ret;
> +
> // HACK: we have no idea if it is a keyframe,
> // but if we mark none seeking will not work at all.
> pkt->flags |= AV_PKT_FLAG_KEY;
> pkt->pos = pos;
> pkt->pts = AV_RL32(&hdr[4]);
> pkt->stream_index = ctx->v_id;
> + if(hdr[2] == 0) {
> + AVStream *st = s->streams[pkt->stream_index];
> + pkt->flags |= PKT_FLAG_KEY;
> + av_add_index_entry(st, pkt->pos, pkt->pts, size + HDRSIZE, 0, AVINDEX_KEYFRAME);
> + }
Setting PKT_FLAG_KEY _twice_ sure won't make it set any more.
Also, the generic code is supposed to handle adding index entries in this way.
And indeed we have
> .flags = AVFMT_GENERIC_INDEX,
So this means we end having index entries double.
Now, using hdr[2] to indicate keyframes looks like a good idea, but I
tried that originally and there are just too many files around where it
is not set or not set correctly.
> @@ -257,6 +263,83 @@ static int nuv_packet(AVFormatContext *s, AVPacket *pkt) {
> return AVERROR(EIO);
> }
>
> +/**
> + * \brief looks for the string RTjjjjjjjjjj in the stream too resync reading
> + * \return TRUE if the syncword is found.
Uh, no, it returns 1, not TRUE
> +static int nuv_resync(AVFormatContext *s, int64_t pos_limit) {
> + ByteIOContext *pb = s->pb;
> + uint32_t tag;
> +
> + tag = get_be32(pb);
> + while(!url_feof(pb) && url_ftell(pb) < pos_limit) {
> + if(tag != MKBETAG('R','T','j','j')) {
> + tag = (tag << 8) | get_byte(pb);
> + continue;
> + }
> + tag = get_be32(pb);
> + if(tag != MKBETAG('j','j','j','j'))
> + continue;
> +
> + tag = get_be32(pb);
> + if(tag != MKBETAG('j','j','j','j'))
> + continue;
> +
> + return 1;
> + }
This calls url_ftell a bit often.
I'd suggest something like
uint64_t tag = get_be64(pb);
while (!url_feof(pb) && url_ftell(pb) < pos_limit) {
int i = 0;
if ((tag & 0xffffff) != AV_RB24("jjj")) {
tag = (tag << 32) | get_be32(pb);
continue;
}
while (i++ < 3 && (tag >> 32) != AV_RB32("RTjj"))
tag = (tag << 8) | get_byte(pb);
if (tag != AV_RB64("RTjjjjjj"))
continue;
tag = (tag << 32) | get_be32(pb);
if ((uint32_t)tag != AV_RB32("jjjj"))
continue;
return 1;
}
return 0;
> +/**
> + * \brief attempts to read a timestamp from stream at the given stream position
> + * \return timestamp if successfull and AV_NOPTS_VALUE if failure
> + */
> +static int64_t nuv_read_dts(AVFormatContext *s, int stream_index,
> + int64_t *ppos, int64_t pos_limit)
If the description and other places use the term "read timestamp" it makes
sense to call the function "nuv_read_timestamp".
> + NUVContext *ctx = s->priv_data;
> + ByteIOContext *pb = s->pb;
> + uint8_t hdr[HDRSIZE];
> + nuv_frametype frametype;
> + int size;
> + int64_t pos, dts;
> +
> + if (url_fseek(pb, *ppos, SEEK_SET) < 0)
> + return AV_NOPTS_VALUE;
Is there any reason we can't do this in common code?
Like this we can't even pass the error value up...
> + while (!url_feof(pb) && url_ftell(pb) < pos_limit) {
> + if (get_buffer(pb, hdr, HDRSIZE) <= 0)
I think anything < HDRSIZE is a problem...
> + // TODO - add general support in av_gen_search, so it adds positions after reading timestamps
> + av_add_index_entry(s->streams[frametype == NUV_VIDEO ? ctx->v_id : ctx->a_id]
> + , pos, dts, size + HDRSIZE, 0, hdr[2] == 0 ? AVINDEX_KEYFRAME : 0);
Unless this makes a large speed difference I am against this.
More information about the ffmpeg-devel
mailing list