[FFmpeg-devel,V2,1/4] lavformat/rm: Add decoding of MLTI chunks, prefer audio, dts for multiple streams, several muxer fixes depending on codec id

Submitted by Thilo Borgmann on Feb. 2, 2018, 2:43 a.m.

Details

Message ID 86a53294-793c-8372-4991-c2a8e0bb0b88@mail.de
State New
Headers show

Commit Message

Thilo Borgmann Feb. 2, 2018, 2:43 a.m.
All of these should be valid for RMVB (file format version 1).

I have no .rm files to test these changes, only .rmhd ones. AAC muxing yet not included, requires file format version 2. However, if all muxer changes are applied, all existing FATE tests involving .rm muxing/demuxing pass for me.

-Thilo
From c6acdc9eb68b384822345aae7e12e84c05720180 Mon Sep 17 00:00:00 2001
From: Thilo Borgmann <thilo.borgmann@mail.de>
Date: Fri, 2 Feb 2018 02:48:34 +0100
Subject: [PATCH 1/4] lavformat/rm: Add decoding of MLTI chunks, prefer audio
 dts for multiple streams, several muxer fixes depending on codec id

---
 libavformat/rmdec.c | 35 +++++++++++++++++++++++++++++++----
 libavformat/rmenc.c | 30 +++++++++++++++++++++++++-----
 2 files changed, 56 insertions(+), 9 deletions(-)

Patch hide | download patch | download mbox

diff --git a/libavformat/rmdec.c b/libavformat/rmdec.c
index fea71a2..cf3d545 100644
--- a/libavformat/rmdec.c
+++ b/libavformat/rmdec.c
@@ -330,7 +330,20 @@  int ff_rm_read_mdpr_codecdata(AVFormatContext *s, AVIOContext *pb,
     codec_pos = avio_tell(pb);
     v = avio_rb32(pb);
 
-    if (v == MKTAG(0xfd, 'a', 'r', '.')) {
+    if (v == MKBETAG('M', 'L', 'T', 'I')) {
+        int number_of_streams = avio_rb16(pb);
+        int number_of_mdpr;
+        int i;
+        for (i = 0; i < number_of_streams; i++) {
+            avio_rb16(pb);
+        }
+        number_of_mdpr = avio_rb16(pb);
+        if (number_of_mdpr != 1) {
+            avpriv_request_sample(s, "MLTI with multiple MDPR");
+        }
+        avio_rb32(pb);
+        v = avio_rb32(pb);
+    } else if (v == MKTAG(0xfd, 'a', 'r', '.')) {
         /* ra type header */
         if (rm_read_audio_stream_info(s, pb, st, rst, 0))
             return -1;
@@ -1089,7 +1102,9 @@  static int64_t rm_read_dts(AVFormatContext *s, int stream_index,
 {
     RMDemuxContext *rm = s->priv_data;
     int64_t pos, dts;
+    int64_t pos_audio, dts_audio;
     int stream_index2, flags, len, h;
+    int audio_override = 0;
 
     pos = *ppos;
 
@@ -1114,20 +1129,32 @@  static int64_t rm_read_dts(AVFormatContext *s, int stream_index,
             if(!(h & 0x40)){
                 seq = avio_r8(s->pb); len--;
             }
+            if (!(flags & 2)       ||
+                (seq & 0x7F)  != 1 ||
+                stream_index2 != stream_index) {
+                audio_override = 0;
+            }
         }
 
         if((flags&2) && (seq&0x7F) == 1){
             av_log(s, AV_LOG_TRACE, "%d %d-%d %"PRId64" %d\n",
                     flags, stream_index2, stream_index, dts, seq);
             av_add_index_entry(st, pos, dts, 0, 0, AVINDEX_KEYFRAME);
-            if(stream_index2 == stream_index)
+            if(stream_index2 == stream_index) {
+                if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
+                    dts_audio      = dts;
+                    pos_audio      = pos;
+                    audio_override = 1;
+                }
+
                 break;
+            }
         }
 
         avio_skip(s->pb, len);
     }
-    *ppos = pos;
-    return dts;
+    *ppos = (audio_override ? pos_audio : pos);
+    return (audio_override ? dts_audio : dts);
 }
 
 static int rm_read_seek(AVFormatContext *s, int stream_index,
diff --git a/libavformat/rmenc.c b/libavformat/rmenc.c
index 3bff4da..83b0f3c 100644
--- a/libavformat/rmenc.c
+++ b/libavformat/rmenc.c
@@ -152,7 +152,13 @@  static int rv10_write_header(AVFormatContext *ctx,
         } else {
             desc = "The Video Stream";
             mimetype = "video/x-pn-realvideo";
-            codec_data_size = 34;
+            if(stream->par->codec_id == AV_CODEC_ID_RV10 ||
+               stream->par->codec_id == AV_CODEC_ID_RV20 ||
+               stream->par->codec_id == AV_CODEC_ID_RV40) {
+                codec_data_size = 34;
+            } else {
+                codec_data_size = 26 + stream->par->extradata_size;
+            }
         }
 
         ffio_wfourcc(s,"MDPR");
@@ -245,10 +251,21 @@  static int rv10_write_header(AVFormatContext *ctx,
             /* video codec info */
             avio_wb32(s,34); /* size */
             ffio_wfourcc(s, "VIDO");
-            if(stream->par->codec_id == AV_CODEC_ID_RV10)
+            switch (stream->par->codec_id) {
+            case AV_CODEC_ID_RV10:
                 ffio_wfourcc(s,"RV10");
-            else
+                break;
+            case AV_CODEC_ID_RV20:
                 ffio_wfourcc(s,"RV20");
+                break;
+            case AV_CODEC_ID_RV30:
+                ffio_wfourcc(s,"RV30");
+                break;
+            case AV_CODEC_ID_RV40:
+                ffio_wfourcc(s,"RV40");
+                break;
+            }
+
             avio_wb16(s, stream->par->width);
             avio_wb16(s, stream->par->height);
 
@@ -346,8 +363,11 @@  static int rm_write_header(AVFormatContext *s)
             break;
         case AVMEDIA_TYPE_VIDEO:
             rm->video_stream = stream;
-            // TODO: should be avg_frame_rate
-            stream->frame_rate = av_inv_q(st->time_base);
+            if (st->codecpar->codec_id == AV_CODEC_ID_RV40) {
+                stream->frame_rate = st->avg_frame_rate;
+            } else {
+                stream->frame_rate = av_inv_q(st->time_base);
+            }
             /* XXX: dummy values */
             stream->packet_max_size = 4096;
             stream->nb_packets = 0;