]> git.sesse.net Git - ffmpeg/blobdiff - libavformat/rmdec.c
Support demuxing Blu-ray subtitles in matroska files.
[ffmpeg] / libavformat / rmdec.c
index d53918fc7030dd5749a401500344443325c4c732..be01286695aa6ed7172a6749390be20e72418cff 100644 (file)
@@ -63,7 +63,7 @@ static const AVCodecTag rm_codec_tags[] = {
     { CODEC_ID_SIPR,   MKTAG('s','i','p','r') },
     { CODEC_ID_AAC,    MKTAG('r','a','a','c') },
     { CODEC_ID_AAC,    MKTAG('r','a','c','p') },
-    { 0 },
+    { CODEC_ID_NONE },
 };
 
 static const unsigned char sipr_swaps[38][2] = {
@@ -100,6 +100,20 @@ static void get_str8(ByteIOContext *pb, char *buf, int buf_size)
     get_strl(pb, buf, buf_size, get_byte(pb));
 }
 
+static int rm_read_extradata(ByteIOContext *pb, AVCodecContext *avctx, unsigned size)
+{
+    if (size >= 1<<24)
+        return -1;
+    avctx->extradata = av_malloc(size + FF_INPUT_BUFFER_PADDING_SIZE);
+    if (!avctx->extradata)
+        return AVERROR_NOMEM;
+    avctx->extradata_size = get_buffer(pb, avctx->extradata, size);
+    memset(avctx->extradata + avctx->extradata_size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
+    if (avctx->extradata_size != size)
+        return AVERROR(EIO);
+    return 0;
+}
+
 static void rm_read_metadata(AVFormatContext *s, int wide)
 {
     char buf[1024];
@@ -128,6 +142,7 @@ static int rm_read_audio_stream_info(AVFormatContext *s, ByteIOContext *pb,
 {
     char buf[256];
     uint32_t version;
+    int ret;
 
     /* ra type header */
     version = get_be16(pb); /* version */
@@ -230,9 +245,8 @@ static int rm_read_audio_stream_info(AVFormatContext *s, ByteIOContext *pb,
                 }
                 st->codec->block_align = ast->sub_packet_size;
             }
-            st->codec->extradata_size= codecdata_length;
-            st->codec->extradata= av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
-            get_buffer(pb, st->codec->extradata, st->codec->extradata_size);
+            if ((ret = rm_read_extradata(pb, st->codec, codecdata_length)) < 0)
+                return ret;
 
             if(ast->audio_framesize >= UINT_MAX / sub_packet_h){
                 av_log(s, AV_LOG_ERROR, "rm->audio_framesize * sub_packet_h too large\n");
@@ -252,10 +266,9 @@ static int rm_read_audio_stream_info(AVFormatContext *s, ByteIOContext *pb,
                 return -1;
             }
             if (codecdata_length >= 1) {
-                st->codec->extradata_size = codecdata_length - 1;
-                st->codec->extradata = av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
                 get_byte(pb);
-                get_buffer(pb, st->codec->extradata, st->codec->extradata_size);
+                if ((ret = rm_read_extradata(pb, st->codec, codecdata_length - 1)) < 0)
+                    return ret;
             }
             break;
         default:
@@ -278,6 +291,7 @@ ff_rm_read_mdpr_codecdata (AVFormatContext *s, ByteIOContext *pb,
     unsigned int v;
     int size;
     int64_t codec_pos;
+    int ret;
 
     av_set_pts_info(st, 64, 1, 1000);
     codec_pos = url_ftell(pb);
@@ -307,27 +321,20 @@ ff_rm_read_mdpr_codecdata (AVFormatContext *s, ByteIOContext *pb,
         fps2= get_be16(pb);
         get_be16(pb);
 
-        st->codec->extradata_size= codec_data_size - (url_ftell(pb) - codec_pos);
-
-        if(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE <= (unsigned)st->codec->extradata_size){
-            //check is redundant as get_buffer() will catch this
-            av_log(s, AV_LOG_ERROR, "st->codec->extradata_size too large\n");
-            return -1;
-        }
-        st->codec->extradata= av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
-        if (!st->codec->extradata)
-            return AVERROR(ENOMEM);
-        get_buffer(pb, st->codec->extradata, st->codec->extradata_size);
+        if ((ret = rm_read_extradata(pb, st->codec, codec_data_size - (url_ftell(pb) - codec_pos))) < 0)
+            return ret;
 
 //        av_log(s, AV_LOG_DEBUG, "fps= %d fps2= %d\n", fps, fps2);
         st->codec->time_base.den = fps * st->codec->time_base.num;
         //XXX: do we really need that?
-        switch(((uint8_t*)st->codec->extradata)[4]>>4){
+        switch(st->codec->extradata[4]>>4){
         case 1: st->codec->codec_id = CODEC_ID_RV10; break;
         case 2: st->codec->codec_id = CODEC_ID_RV20; break;
         case 3: st->codec->codec_id = CODEC_ID_RV30; break;
         case 4: st->codec->codec_id = CODEC_ID_RV40; break;
-        default: goto fail1;
+        default:
+            av_log(st->codec, AV_LOG_ERROR, "extra:%02X %02X %02X %02X %02X\n", st->codec->extradata[0], st->codec->extradata[1], st->codec->extradata[2], st->codec->extradata[3], st->codec->extradata[4]);
+            goto fail1;
         }
     }
 
@@ -555,6 +562,9 @@ static int sync(AVFormatContext *s, int64_t *timestamp, int *flags, int *stream_
                 if(len<0)
                     continue;
                 goto skip;
+            } else if (state == MKBETAG('D','A','T','A')) {
+                av_log(s, AV_LOG_WARNING,
+                       "DATA tag in middle of chunk, file may be broken.\n");
             }
 
             if(state > (unsigned)0xFFFF || state <= 12)