diff rm.c @ 879:1f093ae472d8 libavformat

Cook compatibe decoder, patch by Benjamin Larsson Add cook demucing, change rm demuxer so that it reorders audio packets before sending them to the decoder, and send minimum decodeable sized packets; pass only real codec extradata fo the decoder Fix 28_8 decoder for the new demuxer strategy
author rtognimp
date Fri, 09 Dec 2005 16:08:18 +0000
parents 66cc656ea404
children 2ece9c9dd94c
line wrap: on
line diff
--- a/rm.c	Mon Dec 05 20:44:56 2005 +0000
+++ b/rm.c	Fri Dec 09 16:08:18 2005 +0000
@@ -42,6 +42,14 @@
     int old_format;
     int current_stream;
     int remaining_len;
+    /// Audio descrambling matrix parameters
+    uint8_t *audiobuf; ///< place to store reordered audio data
+    int64_t audiotimestamp; ///< Audio packet timestamp
+    int sub_packet_cnt; // Subpacket counter, used while reading
+    int sub_packet_size, sub_packet_h, coded_framesize; ///< Descrambling parameters from container
+    int audio_stream_num; ///< Stream number for audio packets
+    int audio_pkt_cnt; ///< Output packet counter
+    int audio_framesize; /// Audio frame size from container
 } RMContext;
 
 #ifdef CONFIG_MUXERS
@@ -478,6 +486,7 @@
 static void rm_read_audio_stream_info(AVFormatContext *s, AVStream *st, 
                                       int read_all)
 {
+    RMContext *rm = s->priv_data;
     ByteIOContext *pb = &s->pb;
     char buf[128];
     uint32_t version;
@@ -500,39 +509,60 @@
         st->codec->codec_type = CODEC_TYPE_AUDIO;
         st->codec->codec_id = CODEC_ID_RA_144;
     } else {
-        int flavor, sub_packet_h, coded_framesize;
+        int flavor, sub_packet_h, coded_framesize, sub_packet_size;
         /* old version (4) */
         get_be32(pb); /* .ra4 */
         get_be32(pb); /* data size */
         get_be16(pb); /* version2 */
         get_be32(pb); /* header size */
         flavor= get_be16(pb); /* add codec info / flavor */
-        coded_framesize= get_be32(pb); /* coded frame size */
+        rm->coded_framesize = coded_framesize = get_be32(pb); /* coded frame size */
         get_be32(pb); /* ??? */
         get_be32(pb); /* ??? */
         get_be32(pb); /* ??? */
-        sub_packet_h= get_be16(pb); /* 1 */ 
+        rm->sub_packet_h = sub_packet_h = get_be16(pb); /* 1 */ 
         st->codec->block_align= get_be16(pb); /* frame size */
-        get_be16(pb); /* sub packet size */
+        rm->sub_packet_size = sub_packet_size = get_be16(pb); /* sub packet size */
         get_be16(pb); /* ??? */
+        if (((version >> 16) & 0xff) == 5) {
+            get_be16(pb); get_be16(pb); get_be16(pb); }
         st->codec->sample_rate = get_be16(pb);
         get_be32(pb);
         st->codec->channels = get_be16(pb);
+        if (((version >> 16) & 0xff) == 5) {
+            get_be32(pb);
+	    buf[0] = get_byte(pb);
+	    buf[1] = get_byte(pb);
+	    buf[2] = get_byte(pb);
+	    buf[3] = get_byte(pb);
+	    buf[4] = 0;
+	} else {
         get_str8(pb, buf, sizeof(buf)); /* desc */
         get_str8(pb, buf, sizeof(buf)); /* desc */
+	}
         st->codec->codec_type = CODEC_TYPE_AUDIO;
         if (!strcmp(buf, "dnet")) {
             st->codec->codec_id = CODEC_ID_AC3;
         } else if (!strcmp(buf, "28_8")) {
             st->codec->codec_id = CODEC_ID_RA_288;
-            st->codec->extradata_size= 10;
+            st->codec->extradata_size= 0;
+            rm->audio_framesize = st->codec->block_align;
+            st->codec->block_align = coded_framesize;
+            rm->audiobuf = av_malloc(rm->audio_framesize * sub_packet_h);
+        } else if (!strcmp(buf, "cook")) {
+            int codecdata_length, i;
+            get_be16(pb); get_byte(pb);
+            if (((version >> 16) & 0xff) == 5)
+                get_byte(pb);
+            codecdata_length = get_be32(pb);
+            st->codec->codec_id = CODEC_ID_COOK;
+            st->codec->extradata_size= codecdata_length;
             st->codec->extradata= av_mallocz(st->codec->extradata_size);
-            /* this is completly braindead and broken, the idiot who added this codec and endianness
-               specific reordering to mplayer and libavcodec/ra288.c should be drowned in a see of cola */
-            //FIXME pass the unpermutated extradata
-            ((uint16_t*)st->codec->extradata)[1]= sub_packet_h;
-            ((uint16_t*)st->codec->extradata)[2]= flavor;
-            ((uint16_t*)st->codec->extradata)[3]= coded_framesize;
+            for(i = 0; i < codecdata_length; i++)
+                ((uint8_t*)st->codec->extradata)[i] = get_byte(pb);
+            rm->audio_framesize = st->codec->block_align;
+            st->codec->block_align = rm->sub_packet_size;
+            rm->audiobuf = av_malloc(rm->audio_framesize * sub_packet_h);
         } else {
             st->codec->codec_id = CODEC_ID_NONE;
             pstrcpy(st->codec->codec_name, sizeof(st->codec->codec_name),
@@ -819,6 +849,16 @@
         }
         pkt->size = len;
         st = s->streams[0];
+    } else if (rm->audio_pkt_cnt) {
+        // If there are queued audio packet return them first
+        st = s->streams[rm->audio_stream_num];
+        av_new_packet(pkt, st->codec->block_align);
+        memcpy(pkt->data, rm->audiobuf + st->codec->block_align *
+               (rm->sub_packet_h * rm->audio_framesize / st->codec->block_align - rm->audio_pkt_cnt),
+               st->codec->block_align);
+        rm->audio_pkt_cnt--;
+        pkt->flags = 0;
+        pkt->stream_index = rm->audio_stream_num;
     } else {
         int seq=1;
 resync:
@@ -850,15 +890,57 @@
             if(len2 && len2<len)
                 len=len2;
             rm->remaining_len-= len;
+            av_get_packet(pb, pkt, len);
+        }
+
+        if (st->codec->codec_type == CODEC_TYPE_AUDIO) {
+            if ((st->codec->codec_id == CODEC_ID_RA_288) ||
+                (st->codec->codec_id == CODEC_ID_COOK)) {
+                int x;
+                int sps = rm->sub_packet_size;
+                int cfs = rm->coded_framesize;
+                int h = rm->sub_packet_h;
+                int y = rm->sub_packet_cnt;
+                int w = rm->audio_framesize;
+
+                if (flags & 2)
+                    y = rm->sub_packet_cnt = 0;
+                if (!y)
+                    rm->audiotimestamp = timestamp;
+
+                switch(st->codec->codec_id) {
+                    case CODEC_ID_RA_288:
+                        for (x = 0; x < h/2; x++)
+                            get_buffer(pb, rm->audiobuf+x*2*w+y*cfs, cfs);
+                        break;
+                    case CODEC_ID_COOK:
+                        for (x = 0; x < w/sps; x++)
+                            get_buffer(pb, rm->audiobuf+sps*(h*x+((h+1)/2)*(y&1)+(y>>1)), sps);
+                        break;
+                }
+
+                if (++(rm->sub_packet_cnt) < h)
+                    goto resync;
+                else {
+                    rm->sub_packet_cnt = 0;
+                    rm->audio_stream_num = i;
+                    rm->audio_pkt_cnt = h * w / st->codec->block_align - 1;
+                    // Release first audio packet
+                    av_new_packet(pkt, st->codec->block_align);
+                    memcpy(pkt->data, rm->audiobuf, st->codec->block_align);
+                    timestamp = rm->audiotimestamp;
+                    flags = 2; // Mark first packet as keyframe
+                }
+            } else
+                av_get_packet(pb, pkt, len);
         }
 
         if(  (st->discard >= AVDISCARD_NONKEY && !(flags&2))
            || st->discard >= AVDISCARD_ALL){
-            url_fskip(pb, len);
+            av_free_packet(pkt);
             goto resync;
         }
         
-        av_get_packet(pb, pkt, len);
         pkt->stream_index = i;
 
 #if 0
@@ -896,6 +978,9 @@
 
 static int rm_read_close(AVFormatContext *s)
 {
+    RMContext *rm = s->priv_data;
+
+    av_free(rm->audiobuf);
     return 0;
 }