[Ffmpeg-devel] AVPaletteControl removal from libavf (was Re: [MPlayer-dev-eng] [PATCH] (bit hackish) palette support for libav*)

Reimar Döffinger Reimar.Doeffinger
Mon Jan 29 23:03:26 CET 2007


Hello,
On Mon, Jan 29, 2007 at 09:26:54PM +0100, Reimar D?ffinger wrote:
> On Mon, Jan 29, 2007 at 07:19:15PM +0100, Michael Niedermayer wrote:
> > On Mon, Jan 29, 2007 at 06:22:30PM +0100, Reimar D?ffinger wrote:
> > > On Mon, Jan 29, 2007 at 05:52:54PM +0100, Michael Niedermayer wrote:
> [...]
> > > > palette changes should be sent as packets like normal frames
> > > 
> > > That might make things quite a bit simpler from the MPlayer side.
> > > Do you have something in mind already?
> > > Just adding PKT_FLAG_PALETTE and sending the palette through? Might
> > 
> > yes
> 
> Hm.. little problem... Either I move the palette handling into the main
> loop, which will not work for codecs that have a delay, or I need to
> pass the palette into the codec somehow...
> Any suggestions?
> My first idea is keeping AVPaletteControl, but using it only in
> libavcodec...

Here is what I came up with so far (MPlayer only). I still have to
investigate where the changes in ffmpeg must go to (second attached
patch is for changes needed to ffplay).
Does this look like the right way to proceed?

Greetings,
Reimar D?ffinger
-------------- next part --------------
Index: libavformat/ipmovie.c
===================================================================
--- libavformat/ipmovie.c	(revision 7760)
+++ libavformat/ipmovie.c	(working copy)
@@ -116,8 +116,7 @@
 
     offset_t next_chunk_offset;
 
-    AVPaletteControl palette_control;
-
+    uint32_t palette[AVPALETTE_SIZE];
 } IPMVEContext;
 
 static int load_ipmovie_packet(IPMVEContext *s, ByteIOContext *pb,
@@ -224,6 +223,7 @@
     int first_color, last_color;
     int audio_flags;
     unsigned char r, g, b;
+    int palette_changed;
 
     /* see if there are any pending packets */
     chunk_type = load_ipmovie_packet(s, pb, pkt);
@@ -458,10 +458,9 @@
                 r = scratch[j++] * 4;
                 g = scratch[j++] * 4;
                 b = scratch[j++] * 4;
-                s->palette_control.palette[i] = (r << 16) | (g << 8) | (b);
+                s->palette[i] = (r << 16) | (g << 8) | (b);
             }
-            /* indicate a palette change */
-            s->palette_control.palette_changed = 1;
+            palette_changed = 1;
             break;
 
         case OPCODE_SET_PALETTE_COMPRESSED:
@@ -498,6 +497,13 @@
     /* make a note of where the stream is sitting */
     s->next_chunk_offset = url_ftell(pb);
 
+    if (palette_changed) {
+        if (av_new_packet(pkt, AVPALETTE_SIZE))
+            chunk_type = CHUNK_NOMEM;
+        memcpy(pkt->data, s->palette, AVPALETTE_SIZE);
+        pkt->stream_index = s->video_stream_index;
+        pkt->flags |= PKT_FLAG_PALETTE;
+    } else
     /* dispatch the first of any pending packets */
     if ((chunk_type == CHUNK_VIDEO) || (chunk_type == CHUNK_AUDIO_ONLY))
         chunk_type = load_ipmovie_packet(s, pb, pkt);
@@ -562,9 +568,6 @@
     st->codec->width = ipmovie->video_width;
     st->codec->height = ipmovie->video_height;
 
-    /* palette considerations */
-    st->codec->palctrl = &ipmovie->palette_control;
-
     if (ipmovie->audio_type) {
         st = av_new_stream(s, 0);
         if (!st)
Index: libmpdemux/stheader.h
===================================================================
--- libmpdemux/stheader.h	(revision 22063)
+++ libmpdemux/stheader.h	(working copy)
@@ -4,6 +4,9 @@
 #include "aviheader.h"
 #include "ms_hdr.h"
 
+#define VID_PALETTE_SIZE 1024
+#define VID_PALETTE_NUM 256
+
 // Stream headers:
 
 typedef struct {
@@ -88,6 +91,9 @@
   AVIStreamHeader video;
   BITMAPINFOHEADER* bih;
   void* ImageDesc; // for quicktime codecs
+  int has_palette;
+  int palette_changed;
+  unsigned int palette[VID_PALETTE_NUM];
   // codec-specific:
   void* context;   // codec-specific stuff (usually HANDLE or struct pointer)
 } sh_video_t;
Index: libmpdemux/demux_lavf.c
===================================================================
--- libmpdemux/demux_lavf.c	(revision 22063)
+++ libmpdemux/demux_lavf.c	(working copy)
@@ -420,6 +440,14 @@
             ds->sh=demux->v_streams[id];
             mp_msg(MSGT_DEMUX,MSGL_V,"Auto-selected LAVF video ID = %d\n",ds->id);
         }
+        if (pkt.flags & PKT_FLAG_PALETTE) {
+            sh_video_t *sh = ds->sh;
+            sh->has_palette = 1;
+            sh->palette_changed = 1;
+            memcpy(sh->palette, pkt.data, FFMIN(VID_PALETTE_SIZE, pkt.size));
+            av_free_packet(&pkt);
+            return 1;
+        }
     } else {
         av_free_packet(&pkt);
         return 1;
@@ -446,6 +474,8 @@
     }
     dp->pos=demux->filepos;
     dp->flags= !!(pkt.flags&PKT_FLAG_KEY);
+    if (pkt.flags & PKT_FLAG_PALETTE)
+        dp->flags |= DEMUXER_PKTFLAG_PALETTE;
     // append packet to DS stream:
     ds_add_packet(ds,dp);
     return 1;
Index: libmpcodecs/vd_ffmpeg.c
===================================================================
--- libmpcodecs/vd_ffmpeg.c	(revision 22063)
+++ libmpcodecs/vd_ffmpeg.c	(working copy)
@@ -386,9 +386,12 @@
 	break;
     }
     /* Pass palette to codec */
-    if (sh->bih && (sh->bih->biBitCount <= 8)) {
+    if (sh->bih && (sh->bih->biBitCount <= 8) || sh->has_palette) {
         avctx->palctrl = calloc(1,sizeof(AVPaletteControl));
         avctx->palctrl->palette_changed = 1;
+        if (sh->has_palette)
+            memcpy(avctx->palctrl->palette, sh->palette, FFMIN(VID_PALETTE_SIZE, AVPALETTE_SIZE));
+        else
         if (sh->bih->biSize-sizeof(BITMAPINFOHEADER))
             /* Palette size in biSize */
             memcpy(avctx->palctrl->palette, sh->bih+1,
@@ -747,6 +756,10 @@
 
     avctx->hurry_up=(flags&3)?((flags&2)?2:1):0;
 
+    if (sh->has_palette && sh->palette_changed && avctx->palctrl) {
+        avctx->palctrl->palette_changed = 1;
+        memcpy(avctx->palctrl->palette, sh->palette, FFMIN(VID_PALETTE_SIZE, AVPALETTE_SIZE));
+    }
 //    if(sh->ds->demuxer->type == DEMUXER_TYPE_REAL){
     if(   sh->format == mmioFOURCC('R', 'V', '1', '0')
        || sh->format == mmioFOURCC('R', 'V', '1', '3')
Index: libavformat/avformat.h
===================================================================
--- libavformat/avformat.h	(revision 7760)
+++ libavformat/avformat.h	(working copy)
@@ -51,7 +51,8 @@
     void  *priv;
     int64_t pos;                            ///< byte position in stream, -1 if unknown
 } AVPacket;
-#define PKT_FLAG_KEY   0x0001
+#define PKT_FLAG_KEY      0x0001
+#define PKT_FLAG_PALETTE  0x0002
 
 void av_destruct_packet_nofree(AVPacket *pkt);
 void av_destruct_packet(AVPacket *pkt);
-------------- next part --------------
Index: ffplay.c
===================================================================
--- ffplay.c	(revision 7760)
+++ ffplay.c	(working copy)
@@ -1327,6 +1328,15 @@
             avcodec_flush_buffers(is->video_st->codec);
             continue;
         }
+        if (pkt->flags & PKT_FLAG_PALETTE) {
+            if (!is->video_st->codec->palctrl)
+                is->video_st->codec->palctrl = calloc(1, sizeof(AVPaletteControl));
+            is->video_st->codec->palctrl->palette_changed = 1;
+            memcpy(is->video_st->codec->palctrl->palette, pkt->data,
+                   FFMIN(AVPALETTE_SIZE, pkt->size));
+            av_free_packet(pkt);
+            continue;
+        }
 
         /* NOTE: ipts is the PTS of the _first_ picture beginning in
            this packet, if any */
Index: libavcodec/interplayvideo.c
===================================================================
--- libavcodec/interplayvideo.c	(revision 7760)
+++ libavcodec/interplayvideo.c	(working copy)
@@ -859,11 +859,6 @@
 
     s->avctx = avctx;
 
-    if (s->avctx->palctrl == NULL) {
-        av_log(avctx, AV_LOG_ERROR, " Interplay video: palette expected.\n");
-        return -1;
-    }
-
     avctx->pix_fmt = PIX_FMT_PAL8;
     avctx->has_b_frames = 0;
     dsputil_init(&s->dsp, avctx);
@@ -902,6 +897,10 @@
     IpvideoContext *s = avctx->priv_data;
     AVPaletteControl *palette_control = avctx->palctrl;
 
+    if (!palette_control) {
+        av_log(avctx, AV_LOG_ERROR, " Interplay video: palette expected.\n");
+        return -1;
+    }
     /* compressed buffer needs to be large enough to at least hold an entire
      * decoding map */
     if (buf_size < s->decoding_map_size)



More information about the ffmpeg-devel mailing list