On Sat, Apr 02, 2011 at 04:06:44AM -0700, Ronald S. Bultje wrote:
> Hi,
> 
> On Sat, Apr 2, 2011 at 2:52 AM, Kostya <[email protected]> wrote:
> > I think this can be resolved by passing new palette in AVPacket in some way:
> > 0) do nothing and pretent that problem doesn't exist
> > 1a) just add AV_PKG_FLAG_PAL and make codec treat last 1024 bytes of data as
> > palette (should be done for muxers too). Alternatively packet size may be
> > hacked so palette will be after declared packet end (but that's too hacky to
> > my taste).
> > 1å) add AV_PKT_FLAG_PAL and pass only palette change in packet (it may break
> > timestamp handling, I fear)
> > 2) introduce some specific fields in AVPacket for passing such information
> > (too hacky IMO)
> 
> Since you're implementing it, I think you should choose.
> AV_PKT_FLAG_PAL sounds fine, but it does feel a little clunky. I also
> feel having a new "uint8_t *palette_data;" pointer is fine also, then
> you don't have to change all data to data[0].

Since Luca wants to smuggle something too, I've chosen more generic name.
Proof-of-concept patches attached.
>From d57b24be79701a3d75f868ea6e92e824da95289c Mon Sep 17 00:00:00 2001
From: Kostya Shishkov <[email protected]>
Date: Sat, 2 Apr 2011 14:31:20 +0200
Subject: [PATCH 1/3] introduce side information in AVPacket

---
 libavcodec/avcodec.h  |   16 ++++++++++++++++
 libavcodec/avpacket.c |   35 +++++++++++++++++++++++++++++++++++
 libavcodec/version.h  |    2 +-
 3 files changed, 52 insertions(+), 1 deletions(-)

diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index 4cd78a3..39bb382 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -1054,6 +1054,12 @@ typedef struct AVPacket {
     int64_t dts;
     uint8_t *data;
     int   size;
+    /**
+     * Additional packet data that may be provided by container. If present
+     * it should be also marked in packet flags.
+     */
+    uint8_t *side_data;
+    int   side_data_size;
     int   stream_index;
     int   flags;
     /**
@@ -1085,6 +1091,7 @@ typedef struct AVPacket {
     int64_t convergence_duration;
 } AVPacket;
 #define AV_PKT_FLAG_KEY   0x0001
+#define AV_PKT_FLAG_PAL   0x0002
 #if LIBAVCODEC_VERSION_MAJOR < 53
 #define PKT_FLAG_KEY AV_PKT_FLAG_KEY
 #endif
@@ -3181,6 +3188,15 @@ void av_shrink_packet(AVPacket *pkt, int size);
 int av_grow_packet(AVPacket *pkt, int grow_by);
 
 /**
+ * Allocate the side information of a packet.
+ *
+ * @param pkt packet
+ * @param size wanted side information size
+ * @return 0 if OK, AVERROR_xxx otherwise
+ */
+int av_new_packet_side_data(AVPacket *pkt, int size);
+
+/**
  * @warning This is a hack - the packet memory allocation stuff is broken. The
  * packet is allocated if it was not really allocated.
  */
diff --git a/libavcodec/avpacket.c b/libavcodec/avpacket.c
index f6aef20..18d90d7 100644
--- a/libavcodec/avpacket.c
+++ b/libavcodec/avpacket.c
@@ -26,12 +26,17 @@
 void av_destruct_packet_nofree(AVPacket *pkt)
 {
     pkt->data = NULL; pkt->size = 0;
+    pkt->side_data      = NULL;
+    pkt->side_data_size = 0;
 }
 
 void av_destruct_packet(AVPacket *pkt)
 {
     av_free(pkt->data);
     pkt->data = NULL; pkt->size = 0;
+    av_free(pkt->side_data);
+    pkt->side_data      = NULL;
+    pkt->side_data_size = 0;
 }
 
 void av_init_packet(AVPacket *pkt)
@@ -44,6 +49,8 @@ void av_init_packet(AVPacket *pkt)
     pkt->flags = 0;
     pkt->stream_index = 0;
     pkt->destruct= NULL;
+    pkt->side_data      = NULL;
+    pkt->side_data_size = 0;
 }
 
 int av_new_packet(AVPacket *pkt, int size)
@@ -59,6 +66,8 @@ int av_new_packet(AVPacket *pkt, int size)
     av_init_packet(pkt);
     pkt->data = data;
     pkt->size = size;
+    pkt->side_data      = NULL;
+    pkt->side_data_size = 0;
     pkt->destruct = av_destruct_packet;
     if(!data)
         return AVERROR(ENOMEM);
@@ -89,6 +98,20 @@ int av_grow_packet(AVPacket *pkt, int grow_by)
     return 0;
 }
 
+int av_new_packet_side_data(AVPacket *pkt, int side_data_size)
+{
+    void *new_ptr;
+    if ((unsigned)side_data_size > INT_MAX - FF_INPUT_BUFFER_PADDING_SIZE)
+        return -1;
+    new_ptr = av_malloc(side_data_size + FF_INPUT_BUFFER_PADDING_SIZE);
+    if (!new_ptr)
+        return AVERROR(ENOMEM);
+    pkt->side_data      = new_ptr;
+    pkt->side_data_size = side_data_size;
+    memset(pkt->side_data + pkt->side_data_size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
+    return 0;
+}
+
 int av_dup_packet(AVPacket *pkt)
 {
     if (((pkt->destruct == av_destruct_packet_nofree) || (pkt->destruct == NULL)) && pkt->data) {
@@ -96,6 +119,9 @@ int av_dup_packet(AVPacket *pkt)
         /* We duplicate the packet and don't forget to add the padding again. */
         if((unsigned)pkt->size > (unsigned)pkt->size + FF_INPUT_BUFFER_PADDING_SIZE)
             return AVERROR(ENOMEM);
+        if((unsigned)pkt->side_data_size >
+           (unsigned)pkt->side_data_size + FF_INPUT_BUFFER_PADDING_SIZE)
+            return AVERROR(ENOMEM);
         data = av_malloc(pkt->size + FF_INPUT_BUFFER_PADDING_SIZE);
         if (!data) {
             return AVERROR(ENOMEM);
@@ -103,6 +129,13 @@ int av_dup_packet(AVPacket *pkt)
         memcpy(data, pkt->data, pkt->size);
         memset(data + pkt->size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
         pkt->data = data;
+        data = av_malloc(pkt->side_data_size + FF_INPUT_BUFFER_PADDING_SIZE);
+        if (!data) {
+            return AVERROR(ENOMEM);
+        }
+        memcpy(data, pkt->side_data, pkt->side_data_size);
+        memset(data + pkt->side_data_size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
+        pkt->side_data = data;
         pkt->destruct = av_destruct_packet;
     }
     return 0;
@@ -113,5 +146,7 @@ void av_free_packet(AVPacket *pkt)
     if (pkt) {
         if (pkt->destruct) pkt->destruct(pkt);
         pkt->data = NULL; pkt->size = 0;
+        pkt->side_data      = NULL;
+        pkt->side_data_size = 0;
     }
 }
diff --git a/libavcodec/version.h b/libavcodec/version.h
index 5aa0b82..ffce026 100644
--- a/libavcodec/version.h
+++ b/libavcodec/version.h
@@ -21,7 +21,7 @@
 #define AVCODEC_VERSION_H
 
 #define LIBAVCODEC_VERSION_MAJOR 52
-#define LIBAVCODEC_VERSION_MINOR 117
+#define LIBAVCODEC_VERSION_MINOR 118
 #define LIBAVCODEC_VERSION_MICRO  0
 
 #define LIBAVCODEC_VERSION_INT  AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
-- 
1.7.0.4

>From 08aab2f9ea161b1af2add617255e7e80b2970518 Mon Sep 17 00:00:00 2001
From: Kostya Shishkov <[email protected]>
Date: Sat, 2 Apr 2011 15:48:50 +0200
Subject: [PATCH 2/3] make AVI demuxer pass palette in packet

---
 libavformat/avidec.c |   17 +++++++++--------
 1 files changed, 9 insertions(+), 8 deletions(-)

diff --git a/libavformat/avidec.c b/libavformat/avidec.c
index 43ced28..d5927b4 100644
--- a/libavformat/avidec.c
+++ b/libavformat/avidec.c
@@ -598,6 +598,8 @@ static int avi_read_header(AVFormatContext *s, AVFormatParameters *ap)
                                FFMIN(st->codec->extradata_size, AVPALETTE_SIZE));
 #endif
                         st->codec->palctrl->palette_changed = 1;
+                        ast->has_pal = 1;
+                        memcpy(ast->pal, st->codec->palctrl->palette, AVPALETTE_SIZE);
                     }
 
                     print_tag("video", tag1, 0);
@@ -929,14 +931,13 @@ resync:
             return err;
 
         if(ast->has_pal && pkt->data && pkt->size<(unsigned)INT_MAX/2){
-            void *ptr= av_realloc(pkt->data, pkt->size + 4*256 + FF_INPUT_BUFFER_PADDING_SIZE);
-            if(ptr){
-            ast->has_pal=0;
-            pkt->size += 4*256;
-            pkt->data= ptr;
-                memcpy(pkt->data + pkt->size - 4*256, ast->pal, 4*256);
-            }else
-                av_log(s, AV_LOG_ERROR, "Failed to append palette\n");
+            if(av_new_packet_side_data(pkt, 4*256)){
+                av_log(s, AV_LOG_ERROR, "Failed to allocate data for palette\n");
+            }else{
+                memcpy(pkt->side_data, ast->pal, 4*256);
+                pkt->flags |= AV_PKT_FLAG_PAL;
+                ast->has_pal = 0;
+            }
         }
 
         if (CONFIG_DV_DEMUXER && avi->dv_demux) {
-- 
1.7.0.4

>From 597178561575751d93f86b9a5ff72137c58db4a7 Mon Sep 17 00:00:00 2001
From: Kostya Shishkov <[email protected]>
Date: Sat, 2 Apr 2011 15:49:43 +0200
Subject: [PATCH 3/3] read palette from the packet

---
 libavcodec/kmvc.c     |    5 +++++
 libavcodec/msvideo1.c |   15 ++++++++-------
 libavcodec/qpeg.c     |    7 ++++---
 libavcodec/rawdec.c   |    4 ++++
 4 files changed, 21 insertions(+), 10 deletions(-)

diff --git a/libavcodec/kmvc.c b/libavcodec/kmvc.c
index 2671cc6..c42b24e 100644
--- a/libavcodec/kmvc.c
+++ b/libavcodec/kmvc.c
@@ -279,6 +279,11 @@ static int decode_frame(AVCodecContext * avctx, void *data, int *data_size, AVPa
         }
     }
 
+    if (avpkt->flags & AV_PKT_FLAG_PAL) {
+        ctx->pic.palette_has_changed = 1;
+        memcpy(ctx->pal, avpkt->side_data, 1024);
+    }
+
     if (ctx->setpal) {
         ctx->setpal = 0;
         ctx->pic.palette_has_changed = 1;
diff --git a/libavcodec/msvideo1.c b/libavcodec/msvideo1.c
index e01ddf5..f5d580f 100644
--- a/libavcodec/msvideo1.c
+++ b/libavcodec/msvideo1.c
@@ -55,6 +55,7 @@ typedef struct Msvideo1Context {
 
     int mode_8bit;  /* if it's not 8-bit, it's 16-bit */
 
+    uint32_t pal[256];
 } Msvideo1Context;
 
 static av_cold int msvideo1_decode_init(AVCodecContext *avctx)
@@ -173,13 +174,8 @@ static void msvideo1_decode_8bit(Msvideo1Context *s)
     }
 
     /* make the palette available on the way out */
-    if (s->avctx->pix_fmt == PIX_FMT_PAL8) {
-        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;
-        }
-    }
+    if (s->avctx->pix_fmt == PIX_FMT_PAL8)
+        memcpy(s->frame.data[1], s->pal, AVPALETTE_SIZE);
 }
 
 static void msvideo1_decode_16bit(Msvideo1Context *s)
@@ -309,6 +305,11 @@ static int msvideo1_decode_frame(AVCodecContext *avctx,
         return -1;
     }
 
+    if (s->mode_8bit && avpkt->flags & AV_PKT_FLAG_PAL) {
+        memcpy(s->pal, avpkt->side_data, 1024);
+        s->frame.palette_has_changed = 1;
+    }
+
     if (s->mode_8bit)
         msvideo1_decode_8bit(s);
     else
diff --git a/libavcodec/qpeg.c b/libavcodec/qpeg.c
index ccd634a..e8e9e2e 100644
--- a/libavcodec/qpeg.c
+++ b/libavcodec/qpeg.c
@@ -30,6 +30,7 @@ typedef struct QpegContext{
     AVCodecContext *avctx;
     AVFrame pic;
     uint8_t *refdata;
+    uint32_t pal[256];
 } QpegContext;
 
 static void qpeg_decode_intra(const uint8_t *src, uint8_t *dst, int size,
@@ -274,11 +275,11 @@ static int decode_frame(AVCodecContext *avctx,
     }
 
     /* make the palette available on the way out */
-    memcpy(a->pic.data[1], a->avctx->palctrl->palette, AVPALETTE_SIZE);
-    if (a->avctx->palctrl->palette_changed) {
+    if (avpkt->flags & AV_PKT_FLAG_PAL) {
         a->pic.palette_has_changed = 1;
-        a->avctx->palctrl->palette_changed = 0;
+        memcpy(a->pal, avpkt->side_data, AVPALETTE_SIZE);
     }
+    memcpy(a->pic.data[1], a->pal, AVPALETTE_SIZE);
 
     *data_size = sizeof(AVFrame);
     *(AVFrame*)data = a->pic;
diff --git a/libavcodec/rawdec.c b/libavcodec/rawdec.c
index 3c38829..c9b6ab7 100644
--- a/libavcodec/rawdec.c
+++ b/libavcodec/rawdec.c
@@ -162,6 +162,10 @@ static int raw_decode(AVCodecContext *avctx,
         memcpy(frame->data[1], avctx->palctrl->palette, AVPALETTE_SIZE);
         avctx->palctrl->palette_changed = 0;
     }
+    if (avctx->pix_fmt==PIX_FMT_PAL8 && avpkt->flags & AV_PKT_FLAG_PAL) {
+        memcpy(frame->data[1], avpkt->side_data, AVPALETTE_SIZE);
+        frame->palette_has_changed = 0;
+    }
     if(avctx->pix_fmt==PIX_FMT_BGR24 && ((frame->linesize[0]+3)&~3)*avctx->height <= buf_size)
         frame->linesize[0] = (frame->linesize[0]+3)&~3;
 
-- 
1.7.0.4

_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to