[FFmpeg-devel] [PATCH] RTMP seek support

Michael Niedermayer michaelni
Thu Apr 1 01:09:23 CEST 2010


On Tue, Mar 30, 2010 at 06:42:50PM -0700, Howard Chu wrote:
> Howard Chu wrote:
>> Howard Chu wrote:
>>> Howard Chu wrote:
>>>> Howard Chu wrote:
>>>>> This is a first stab at getting seek working on an RTMP stream.
>
>>>>> I've been testing with this stream:
>>>>>
>>>>> gdb --args ./ffplay_g
>>>>> "rtmp://fms.scctv.net/annenberg//vod/world_of_chemistry_01
>>>>> swfurl=http://www.learner.org/vod/swfs/player-licensed.swf
>>>>> pageurl=http://www.learner.org/vod/vod_window.html?pid=793"
>>>>
>>>> Thanks to a tip from uau this is now working.
>
>> Note that the did_rseek flag wouldn't even be needed if the rest of flvdec
>> always read from the start of a frame, instead of reading from the end of 
>> the
>> previous frame, as it currently does. But I took a look at fixing that and 
>> the
>> diff would be pretty large, so I chose this approach instead.
>
> It turned out to be not too bad to correct that, as this patch shows.
>
>> The patch for aviobuf.c is going to be needed regardless - you shouldn't 
>> be
>> setting "s->pos = s->seek()" unconditionally, since s->seek may not be
>> implemented. Storing a -32 in s->pos is bound to screw something else up.
>
> -- 
>   -- Howard Chu
>   CTO, Symas Corp.           http://www.symas.com
>   Director, Highland Sun     http://highlandsun.com/hyc/
>   Chief Architect, OpenLDAP  http://www.openldap.org/project/

> Index: libavformat/flvdec.c
> ===================================================================
> --- libavformat/flvdec.c	(revision 22713)
> +++ libavformat/flvdec.c	(working copy)
> @@ -270,6 +270,7 @@
>  
>      offset = get_be32(s->pb);
>      url_fseek(s->pb, offset, SEEK_SET);
> +    url_fskip(s->pb, 4);
>  
>      s->start_time = 0;
>  
> @@ -295,9 +296,8 @@
>      int64_t dts, pts = AV_NOPTS_VALUE;
>      AVStream *st = NULL;
>  
> - for(;;){
> + do{
>      pos = url_ftell(s->pb);
> -    url_fskip(s->pb, 4); /* size of previous packet */
>      type = get_byte(s->pb);
>      size = get_be24(s->pb);
>      dts = get_be24(s->pb);
> @@ -359,7 +359,7 @@
>      if ((flags & FLV_VIDEO_FRAMETYPE_MASK) == FLV_FRAME_KEY)
>          av_add_index_entry(st, pos, dts, size, 0, AVINDEX_KEYFRAME);
>      break;

> - }
> + } while(url_fskip(s->pb, 4),1);
>  

putting the url_fskip() inside the loop at the end seems cleaner to me

also the url_fskip() movement could be a seperate patch


[...]
> +static int flv_read_seek(AVFormatContext *s, int stream_index,
> +    int64_t ts, int flags)
> +{
> +    int ret = AVERROR_NOTSUPP;
> +
> +    if (url_is_streamed(s->pb))
> +        ret = av_url_read_fseek(s->pb, stream_index, ts, flags);
> +    return ret;
> +}

what if we get the flv from some other non seekable place like a pipe?


> +
>  AVInputFormat flv_demuxer = {
>      "flv",
>      NULL_IF_CONFIG_SMALL("FLV format"),
> @@ -449,6 +464,7 @@
>      flv_probe,
>      flv_read_header,
>      flv_read_packet,
> +    .read_seek = flv_read_seek,
>      .extensions = "flv",
>      .value = CODEC_ID_FLV1,
>  };
> Index: libavformat/librtmp.c
> ===================================================================
> --- libavformat/librtmp.c	(revision 22713)
> +++ libavformat/librtmp.c	(working copy)
> @@ -127,7 +127,9 @@
>          return AVERROR_NOTSUPP;
>  
>      /* seeks are in milliseconds */
> -    timestamp = av_rescale(timestamp, AV_TIME_BASE, 1000);
> +    if (stream_index == -1)
> +        timestamp = av_rescale(timestamp, 1000, AV_TIME_BASE);
> +
>      if (!RTMP_SendSeek(r, timestamp))
>          return -1;
>      return timestamp;

> Index: libavformat/aviobuf.c
> ===================================================================
> --- libavformat/aviobuf.c	(revision 22713)
> +++ libavformat/aviobuf.c	(working copy)
> @@ -698,8 +698,11 @@
>          return AVERROR(ENOSYS);
>      ret = s->read_seek(h, stream_index, timestamp, flags);
>      if(ret >= 0) {
> +        int64_t pos;
>          s->buf_ptr = s->buf_end; // Flush buffer
> -        s->pos = s->seek(h, 0, SEEK_CUR);
> +        pos = s->seek(h, 0, SEEK_CUR);
> +        if (pos != AVERROR(ENOSYS))
> +            s->pos = pos;
>      }
>      return ret;
>  }

shouldnt this return some kind of error if seek fails?


[...]
-- 
Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

Many that live deserve death. And some that die deserve life. Can you give
it to them? Then do not be too eager to deal out death in judgement. For
even the very wise cannot see all ends. -- Gandalf
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: Digital signature
URL: <http://lists.mplayerhq.hu/pipermail/ffmpeg-devel/attachments/20100401/0f6c5121/attachment.pgp>



More information about the ffmpeg-devel mailing list