This version of the patch set returns to using a pointer to a pointer to the palette in ff_get_packet_palette(), rather than the slightly more expensive behaviour of using memcpy().

As before, it normalizes the palette in AVPacket.data to native endian, since that's the most logical and natural way of handling the palette in a muxer in my book, and we need a common denominator.

Please try stream copy to and from avi/mov with the files below. Also try -vcodec rawvideo.

QuickTime Animation (RLE):
https://drive.google.com/open?id=0B3_pEBoLs0faREo1SlRydmV1LU0

QuickTime Graphics (SMC):
https://drive.google.com/open?id=0B3_pEBoLs0faODd5RVBldkdvVGc

Microsoft Video 1 (CRAM)
https://drive.google.com/open?id=0B3_pEBoLs0faT2ZZZVNpVUM0blE

--
Mats Peterson
http://matsp888.no-ip.org/~mats/
>From f4a25fbe82ec9fe44f001a39f4eef6a20fc91555 Mon Sep 17 00:00:00 2001
From: Mats Peterson <matsp...@yahoo.com>
Date: Fri, 4 Mar 2016 02:56:26 +0100
Subject: [PATCH v6 1/4] lavf/avienc: Add support for palette side data

---
 libavformat/avienc.c |   56 ++++++++++++++++++++++++++++++++------------------
 1 file changed, 36 insertions(+), 20 deletions(-)

diff --git a/libavformat/avienc.c b/libavformat/avienc.c
index ca505f4..ad90537 100644
--- a/libavformat/avienc.c
+++ b/libavformat/avienc.c
@@ -74,12 +74,12 @@ typedef struct AVIStream {
     int max_size;
     int sample_requested;
 
-    int64_t pal_offset;
-    int hdr_pal_done;
-
     int64_t last_dts;
 
     AVIIndex indexes;
+
+    int64_t hdr_pal_offset;
+    int hdr_pal_done;
 } AVIStream;
 
 static int avi_write_packet_internal(AVFormatContext *s, AVPacket *pkt);
@@ -362,7 +362,8 @@ static int avi_write_header(AVFormatContext *s)
                     && enc->pix_fmt == AV_PIX_FMT_RGB555LE
                     && enc->bits_per_coded_sample == 15)
                     enc->bits_per_coded_sample = 16;
-                avist->pal_offset = avio_tell(pb) + 40;
+                if (pb->seekable)
+                    avist->hdr_pal_offset = avio_tell(pb) + 40;
                 ff_put_bmp_header(pb, enc, ff_codec_bmp_tags, 0, 0);
                 pix_fmt = avpriv_find_pix_fmt(avpriv_pix_fmt_bps_avi,
                                               enc->bits_per_coded_sample);
@@ -652,11 +653,11 @@ static int avi_write_packet(AVFormatContext *s, AVPacket *pkt)
 {
     unsigned char tag[5];
     const int stream_index = pkt->stream_index;
-    const uint8_t *data    = pkt->data;
-    int size               = pkt->size;
     AVIOContext *pb     = s->pb;
     AVCodecContext *enc = s->streams[stream_index]->codec;
     AVIStream *avist    = s->streams[stream_index]->priv_data;
+    AVPacket *opkt = pkt;
+    enum AVPixelFormat pix_fmt = enc->pix_fmt;
     int ret;
 
     if (enc->codec_id == AV_CODEC_ID_H264 && enc->codec_tag == MKTAG('H','2','6','4') && pkt->size) {
@@ -668,22 +669,35 @@ static int avi_write_packet(AVFormatContext *s, AVPacket *pkt)
     if ((ret = write_skip_frames(s, stream_index, pkt->dts)) < 0)
         return ret;
 
-    if (enc->codec_id == AV_CODEC_ID_RAWVIDEO && enc->codec_tag == 0) {
-        int64_t bpc = enc->bits_per_coded_sample != 15 ? enc->bits_per_coded_sample : 16;
-        int expected_stride = ((enc->width * bpc + 31) >> 5)*4;
-
-        ret = ff_reshuffle_raw_rgb(s, &pkt, enc, expected_stride);
-        if (ret < 0)
-            return ret;
-        if (ret) {
-            if (ret == CONTAINS_PAL) {
-                int pc_tag, i;
+    if (!pkt->size)
+        return avi_write_packet_internal(s, pkt); /* Passthrough */
+
+    if (enc->codec_type == AVMEDIA_TYPE_VIDEO) {
+        if (enc->codec_id == AV_CODEC_ID_RAWVIDEO && enc->codec_tag == 0) {
+            int64_t bpc = enc->bits_per_coded_sample != 15 ? enc->bits_per_coded_sample : 16;
+            int expected_stride = ((enc->width * bpc + 31) >> 5)*4;
+            ret = ff_reshuffle_raw_rgb(s, &pkt, enc, expected_stride);
+            if (ret < 0)
+                return ret;
+        } else
+            ret = 0;
+        if (pix_fmt == AV_PIX_FMT_NONE && enc->bits_per_coded_sample == 1)
+            pix_fmt = AV_PIX_FMT_MONOWHITE;
+        if (pix_fmt == AV_PIX_FMT_PAL8 ||
+            pix_fmt == AV_PIX_FMT_MONOWHITE ||
+            pix_fmt == AV_PIX_FMT_MONOBLACK) {
+            uint32_t *pal;
+            int ret2 = ff_get_packet_palette(s, opkt, ret, &pal);
+            if (ret2 < 0)
+                return ret2;
+            if (pal) {
                 int pal_size = 1 << enc->bits_per_coded_sample;
-                if (!avist->hdr_pal_done) {
+                int pc_tag, i;
+                if (pb->seekable && !avist->hdr_pal_done) {
                     int64_t cur_offset = avio_tell(pb);
-                    avio_seek(pb, avist->pal_offset, SEEK_SET);
+                    avio_seek(pb, avist->hdr_pal_offset, SEEK_SET);
                     for (i = 0; i < pal_size; i++) {
-                        uint32_t v = AV_RL32(data + size - 4*pal_size + 4*i);
+                        uint32_t v = pal[i];
                         avio_wl32(pb, v & 0xffffff);
                     }
                     avio_seek(pb, cur_offset, SEEK_SET);
@@ -696,11 +710,13 @@ static int avi_write_packet(AVFormatContext *s, AVPacket *pkt)
                 avio_w8(pb, pal_size & 0xFF);
                 avio_wl16(pb, 0); // reserved
                 for (i = 0; i < pal_size; i++) {
-                    uint32_t v = AV_RL32(data + size - 4*pal_size + 4*i);
+                    uint32_t v = pal[i];
                     avio_wb32(pb, v<<8);
                 }
                 ff_end_tag(pb, pc_tag);
             }
+        }
+        if (ret) {
             ret = avi_write_packet_internal(s, pkt);
             av_packet_free(&pkt);
             return ret;
-- 
1.7.10.4

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel

Reply via email to