[FFmpeg-devel] [PATCH] rmdec.c: merge old/new packet reading code

Ronald S. Bultje rsbultje
Wed Mar 11 05:39:41 CET 2009


Hi,

On Tue, Mar 10, 2009 at 6:46 PM, Ronald S. Bultje <rsbultje at gmail.com> wrote:
> It appears seq is an ancient leftover of something that was at some
> point correct keyframe-only index-generation. I'd suggest to throw out
> my initial patch to remove it, I'm working on a better scheme that
> should suffice in creating and generating indexes for index-less
> files.

See attached, it's sort of a poor-mans attempt but there's a lot of
hooks and strings to it if you want it to work correctly. Comment at
the bottom should speak for itself, the index is now written for the
first packet of keyframes (video) or audio, or any audio packet for
AAC/AC3 (where there's no such thing as packet-spreading of samples).

I have another patch that reads indexes from files, I'll submit that shortly.

Ronald
-------------- next part --------------
Index: ffmpeg-svn/libavformat/rmdec.c
===================================================================
--- ffmpeg-svn.orig/libavformat/rmdec.c	2009-03-10 16:20:45.000000000 -0400
+++ ffmpeg-svn/libavformat/rmdec.c	2009-03-11 00:17:06.000000000 -0400
@@ -492,7 +492,8 @@
 
 static int rm_assemble_video_frame(AVFormatContext *s, ByteIOContext *pb,
                                    RMDemuxContext *rm, RMStream *vst,
-                                   AVPacket *pkt, int len)
+                                   AVPacket *pkt, int len,
+                                   int *pseq, int *ptype)
 {
     int hdr, seq, pic_num, len2, pos;
     int type;
@@ -523,10 +524,14 @@
         AV_WL32(pkt->data + 1, 1);
         AV_WL32(pkt->data + 5, 0);
         get_buffer(pb, pkt->data + 9, len);
+        if (ptype) *ptype = type;
         return 0;
     }
     //now we have to deal with single slice
 
+    if (ptype) *ptype = type;
+    if (pseq)  *pseq  = seq;
+
     if((seq & 0x7F) == 1 || vst->curpic_num != pic_num){
         vst->slices = ((hdr & 0x3F) << 1) + 1;
         vst->videobufsize = len2 + 8*vst->slices + 1;
@@ -587,13 +592,13 @@
 int
 ff_rm_parse_packet (AVFormatContext *s, ByteIOContext *pb,
                     AVStream *st, RMStream *ast, int len, AVPacket *pkt,
-                    int *seq, int *flags, int64_t *timestamp)
+                    int *seq, int *type, int *flags, int64_t *timestamp)
 {
     RMDemuxContext *rm = s->priv_data;
 
     if (st->codec->codec_type == CODEC_TYPE_VIDEO) {
         rm->current_stream= st->id;
-        if(rm_assemble_video_frame(s, pb, rm, ast, pkt, len))
+        if(rm_assemble_video_frame(s, pb, rm, ast, pkt, len, seq, type))
             return -1; //got partial frame
     } else if (st->codec->codec_type == CODEC_TYPE_AUDIO) {
         if ((st->codec->codec_id == CODEC_ID_RA_288) ||
@@ -704,7 +709,7 @@
 {
     RMDemuxContext *rm = s->priv_data;
     AVStream *st;
-    int i, len, seq = 1;
+    int i, len, seq, type, res, old_flags;
     int64_t timestamp, pos;
     int flags;
 
@@ -714,9 +719,11 @@
             st = s->streams[rm->audio_stream_num];
             ff_rm_retrieve_cache(s, s->pb, st, st->priv_data, pkt);
         } else {
+            seq = type = 0;
             if (rm->old_format) {
                 RMStream *ast;
 
+                pos = url_ftell(s->pb);
                 st = s->streams[0];
                 ast = st->priv_data;
                 timestamp = AV_NOPTS_VALUE;
@@ -731,8 +738,20 @@
             if(len<0 || url_feof(s->pb))
                 return AVERROR(EIO);
 
-            if (ff_rm_parse_packet (s, s->pb, st, st->priv_data, len, pkt,
-                                    &seq, &flags, &timestamp) < 0)
+            old_flags = flags;
+            res = ff_rm_parse_packet (s, s->pb, st, st->priv_data, len, pkt,
+                                     &seq, &type, &flags, &timestamp);
+
+            /* if no index exists, save an index entry for the first packet
+             * of a sequence of video frame slices leading up to a keyframe,
+             * or for the first packet of an audio sequence. */
+            if ((st->codec->codec_type == CODEC_TYPE_VIDEO &&
+                 (type & 1 || (seq & 0x7F) == 1)) ||
+                (st->codec->codec_type == CODEC_TYPE_AUDIO &&
+                 (old_flags & 2 || res == 0)))
+                av_add_index_entry(st, pos, timestamp, 0, 0, AVINDEX_KEYFRAME);
+
+            if (res < 0)
                 continue;
         }
 
@@ -743,9 +762,6 @@
             break;
     }
 
-    if((flags&2) && (seq&0x7F) == 1)
-        av_add_index_entry(st, pos, timestamp, 0, 0, AVINDEX_KEYFRAME);
-
     return 0;
 }
 
Index: ffmpeg-svn/libavformat/rdt.c
===================================================================
--- ffmpeg-svn.orig/libavformat/rdt.c	2009-03-10 18:55:04.000000000 -0400
+++ ffmpeg-svn/libavformat/rdt.c	2009-03-11 00:15:21.000000000 -0400
@@ -308,7 +308,7 @@
         init_put_byte(&pb, buf, len, 0, NULL, NULL, NULL, NULL);
         flags = (flags & RTP_FLAG_KEY) ? 2 : 0;
         res = ff_rm_parse_packet (rdt->rmctx, &pb, st, rdt->rmst[st->index], len, pkt,
-                                  &flags, timestamp);
+                                  NULL, NULL, &flags, timestamp);
         pos = url_ftell(&pb);
         if (res < 0)
             return res;
Index: ffmpeg-svn/libavformat/rm.h
===================================================================
--- ffmpeg-svn.orig/libavformat/rm.h	2009-03-10 18:55:04.000000000 -0400
+++ ffmpeg-svn/libavformat/rm.h	2009-03-11 00:15:21.000000000 -0400
@@ -59,6 +59,12 @@
  * @param rst Real-specific stream information
  * @param len packet length to read from the input
  * @param pkt packet location to store the parsed packet data
+ * @param seq pointer to location where the video slice sequence number
+ *            will be placed (starts at 1), if available. Can be NULL.
+ * @param type pointer to location where the video frame type will be
+ *             stored; 1/3 implies one-packet-per-frame, otherwise it
+ *             means packets are spread over multiple packets, and 'seq'
+ *             will tell you which slice we just parsed. Can be NULL.
  * @param flags pointer to an integer containing the packet flags, may be
                 updated
  * @param ts pointer to timestamp, may be updated
@@ -68,7 +74,8 @@
  */
 int ff_rm_parse_packet (AVFormatContext *s, ByteIOContext *pb,
                         AVStream *st, RMStream *rst, int len,
-                        AVPacket *pkt, int *flags, int64_t *ts);
+                        AVPacket *pkt, int *seq, int *type,
+                        int *flags, int64_t *ts);
 
 /**
  * Retrieve one cached packet from the rm-context. The real container can



More information about the ffmpeg-devel mailing list