[FFmpeg-devel] [PATCH] mov.c: factorize ff_mov_read_stsd_entries()

Ronald S. Bultje rsbultje
Sat Mar 14 16:47:08 CET 2009


Hi,

On Fri, Mar 13, 2009 at 10:36 PM, Ronald S. Bultje <rsbultje at gmail.com> wrote:
> On Fri, Mar 13, 2009 at 10:28 PM, Baptiste Coudurier
> <baptiste.coudurier at gmail.com> wrote:
>> Humm. multiple stsd, or really multiple palette for one stsd ?
>
> I think it's all under the same stsd, just multiple pseudo-streams
> inside it. I don't get mov at all.

attached is an ugly proof-of-concept patch that sort-of allows
decoding of the MSRLE content. It's ugly, probably breaks any other
file format containing MSRLE, etc.etc., but it sort-of shows how to do
this. Some frames still don't decode correctly (compared to
quicktime), but it looks better than before (where every single frame
was wrong).

Based on this patch, I'd like some feedback on how to implement this
correctly (my patch is clearly wrong).

Ronald
-------------- next part --------------
Index: ffmpeg-svn/libavcodec/msrle.c
===================================================================
--- ffmpeg-svn.orig/libavcodec/msrle.c	2009-03-14 11:44:09.000000000 -0400
+++ ffmpeg-svn/libavcodec/msrle.c	2009-03-14 11:44:26.000000000 -0400
@@ -78,13 +78,14 @@
     }
 
     /* make the palette available */
-    memcpy(s->frame.data[1], s->avctx->palctrl->palette, AVPALETTE_SIZE);
-    if (s->avctx->palctrl->palette_changed) {
-        s->frame.palette_has_changed = 1;
-        s->avctx->palctrl->palette_changed = 0;
-    }
+    //memcpy(s->frame.data[1], s->avctx->palctrl->palette, AVPALETTE_SIZE);
+    //if (s->avctx->palctrl->palette_changed) {
+    //    s->frame.palette_has_changed = 1;
+    //    s->avctx->palctrl->palette_changed = 0;
+    //}
+    memcpy(s->frame.data[1], buf, AVPALETTE_SIZE);
 
-    ff_msrle_decode(avctx, (AVPicture*)&s->frame, avctx->bits_per_coded_sample, buf, buf_size);
+    ff_msrle_decode(avctx, (AVPicture*)&s->frame, avctx->bits_per_coded_sample, buf + AVPALETTE_SIZE, buf_size - AVPALETTE_SIZE);
 
     *data_size = sizeof(AVFrame);
     *(AVFrame*)data = s->frame;
Index: ffmpeg-svn/libavformat/isom.h
===================================================================
--- ffmpeg-svn.orig/libavformat/isom.h	2009-03-14 11:44:09.000000000 -0400
+++ ffmpeg-svn/libavformat/isom.h	2009-03-14 11:44:26.000000000 -0400
@@ -118,6 +118,8 @@
     int wrong_dts; ///< dts are wrong due to negative ctts
     int width;  ///< tkhd width
     int height; ///< tkhd height
+#define MAX_PALETTES 16
+    uint32_t *palette[MAX_PALETTES];
 } MOVStreamContext;
 
 typedef struct MOVContext {
@@ -126,7 +128,6 @@
     int64_t duration; /* duration of the longest track */
     int found_moov; /* when both 'moov' and 'mdat' sections has been found */
     int found_mdat; /* we suppose we have enough data to read the file */
-    AVPaletteControl palette_control;
     DVDemuxContext *dv_demux;
     AVFormatContext *dv_fctx;
     int isom; /* 1 if file is ISO Media (mp4/3gp) */
Index: ffmpeg-svn/libavformat/mov.c
===================================================================
--- ffmpeg-svn.orig/libavformat/mov.c	2009-03-14 11:44:09.000000000 -0400
+++ ffmpeg-svn/libavformat/mov.c	2009-03-14 11:44:26.000000000 -0400
@@ -753,8 +753,17 @@
                 /* for palette traversal */
                 unsigned int color_start, color_count, color_end;
                 unsigned char r, g, b;
+                uint32_t *palette = NULL;
 
-                if (color_greyscale) {
+                if (pseudo_stream_id < MAX_PALETTES) {
+                    palette = sc->palette[pseudo_stream_id] =
+                        av_malloc(sizeof(uint32_t) * 256);
+                } else
+                   av_log(c->fc, AV_LOG_WARNING,
+                          "skipping palette %d/%d for str %d\n",
+                          pseudo_stream_id, entries, st->index);
+
+                if (color_greyscale && palette) {
                     int color_index, color_dec;
                     /* compute the greyscale palette */
                     st->codec->bits_per_coded_sample = color_depth;
@@ -763,13 +772,13 @@
                     color_dec = 256 / (color_count - 1);
                     for (j = 0; j < color_count; j++) {
                         r = g = b = color_index;
-                        c->palette_control.palette[j] =
+                        palette[j] =
                             (r << 16) | (g << 8) | (b);
                         color_index -= color_dec;
                         if (color_index < 0)
                             color_index = 0;
                     }
-                } else if (st->codec->color_table_id) {
+                } else if (st->codec->color_table_id && palette) {
                     const uint8_t *color_table;
                     /* if flag bit 3 is set, use the default palette */
                     color_count = 1 << color_depth;
@@ -784,7 +793,7 @@
                         r = color_table[j * 4 + 0];
                         g = color_table[j * 4 + 1];
                         b = color_table[j * 4 + 2];
-                        c->palette_control.palette[j] =
+                        palette[j] =
                             (r << 16) | (g << 8) | (b);
                     }
                 } else {
@@ -806,15 +815,13 @@
                             get_byte(pb);
                             b = get_byte(pb);
                             get_byte(pb);
-                            c->palette_control.palette[j] =
+                            if (palette)
+                                palette[j] =
                                 (r << 16) | (g << 8) | (b);
                         }
                     }
                 }
-                st->codec->palctrl = &c->palette_control;
-                st->codec->palctrl->palette_changed = 1;
-            } else
-                st->codec->palctrl = NULL;
+            }
         } else if(st->codec->codec_type==CODEC_TYPE_AUDIO) {
             int bits_per_sample, flags;
             uint16_t version = get_be16(pb);
@@ -1320,7 +1327,6 @@
 
     /* Do not need those anymore. */
     av_freep(&sc->chunk_offsets);
-    av_freep(&sc->stsc_data);
     av_freep(&sc->sample_sizes);
     av_freep(&sc->keyframes);
     av_freep(&sc->stts_data);
@@ -1900,6 +1906,26 @@
     ret = av_get_packet(sc->pb, pkt, sample->size);
     if (ret < 0)
         return ret;
+    if (sc->palette[0] && sc->stsc_count) {
+        int idx;
+        uint8_t *data = av_malloc(pkt->size + AVPALETTE_SIZE);
+
+        if (!data) {
+            av_free_packet(pkt);
+            return AVERROR(ENOMEM);
+        }
+        memcpy(data + AVPALETTE_SIZE, pkt->data, pkt->size);
+        av_free(pkt->data);
+        pkt->data = data;
+        pkt->size += AVPALETTE_SIZE;
+        /* find palette */
+        for(idx=0;idx<sc->stsc_count - 1;idx++) {
+            if (sc->current_sample - 1 < sc->stsc_data[idx + 1].first)
+                break;
+        }
+        idx = sc->stsc_data[idx].id - 1;
+        memcpy(data, sc->palette[idx], AVPALETTE_SIZE);
+    }
 #if CONFIG_DV_DEMUXER
     if (mov->dv_demux && sc->dv_audio_container) {
         dv_produce_packet(mov->dv_demux, pkt, pkt->data, pkt->size);
@@ -2002,10 +2028,13 @@
     MOVContext *mov = s->priv_data;
     for(i=0; i<s->nb_streams; i++) {
         MOVStreamContext *sc = s->streams[i]->priv_data;
+        av_freep(&sc->stsc_data);
         av_freep(&sc->ctts_data);
         for (j=0; j<sc->drefs_count; j++)
             av_freep(&sc->drefs[j].path);
         av_freep(&sc->drefs);
+        for (j=0;j<MAX_PALETTES;j++)
+            av_freep(&sc->palette[j]);
         if (sc->pb && sc->pb != s->pb)
             url_fclose(sc->pb);
     }



More information about the ffmpeg-devel mailing list