On Tue, Apr 12, 2011 at 09:13:35PM -0400, Ronald S. Bultje wrote: > Hi, > > On Tue, Apr 12, 2011 at 3:44 AM, Luca Barbato <[email protected]> wrote: > > On 04/09/2011 03:59 PM, Kostya Shishkov wrote: > >> This implementation should work fine with multiple side information types > >> present. > > > >> + uint8_t **side_data; > >> + int *side_data_sizes; > >> + int *side_data_types; > >> + int side_data_elems; > > > > Undecided if a > > > > AVSideData { > > void *data > > int data_type > > } > > > > AVSideData *side_data; > > int side_data_elems; > > > > Is nicer since everything is ordered even if looking up is slower. > > Probably your solution is overall better. Patch Ok. > > Why is it slower? The thing is, it saves a malloc. Not necessarily > important, but still quite nice. > > struct { > uint8_t *data; > int size; > int type; > } side_data[]; > int num_side_datas; > > Suddenly you only need 1 big malloc plus 1 per chunk, instead of 3 big > mallocs (one for datas[], one for sizes[], and one more for types[]) > plus 1 per chunk. > > Also, API-wise it makes sense to have av_packet_new_side_data() return > the newly allocated side_data[] chunk, because then the caller can > directly write into it without having to obtain it first. Same for > av_packet_get_side_data(), it should probably take a third argument > int *size which the function can fill in to the size, prevents having > to loop twice, and I don't see why people would ever want the data > without the size. > > Other than that I think this looks good.
Here are improved patches.
>From cc2f2c0e708fb303dd4a886bf40a9b5af58b77fb Mon Sep 17 00:00:00 2001 From: Kostya Shishkov <[email protected]> Date: Sat, 9 Apr 2011 15:31:39 +0200 Subject: [PATCH 1/2] introduce side information for AVPacket --- libavcodec/avcodec.h | 31 +++++++++++++++++ libavcodec/avpacket.c | 89 +++++++++++++++++++++++++++++++++++++++++++----- libavcodec/version.h | 2 +- 3 files changed, 111 insertions(+), 11 deletions(-) diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 7eb8b52..3ae5ce4 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -1057,6 +1057,17 @@ typedef struct AVPacket { int stream_index; int flags; /** + * Additional packet data that can be provided by the container. + * Packet can contain several types of side information. + */ + struct { + uint8_t *data; + int size; + int type; + } *side_data; + int side_data_elems; + + /** * Duration of this packet in AVStream->time_base units, 0 if unknown. * Equals next_pts - this_pts in presentation order. */ @@ -3202,6 +3213,26 @@ int av_dup_packet(AVPacket *pkt); */ void av_free_packet(AVPacket *pkt); +/** + * Allocate new information of a packet. + * + * @param pkt packet + * @param type side information type + * @param size side information size + * @return pointer to fresh allocated data or NULL otherwise + */ +uint8_t* av_packet_new_side_data(AVPacket *pkt, int type, int size); + +/** + * Get side information from packet. + * + * @param pkt packet + * @param type desired side information type + * @param size pointer for side information size to store (optional) + * @return pointer to data if present or NULL otherwise + */ +uint8_t* av_packet_get_side_data(AVPacket *pkt, int type, int *size); + /* resample.c */ struct ReSampleContext; diff --git a/libavcodec/avpacket.c b/libavcodec/avpacket.c index f6aef20..a9542e5 100644 --- a/libavcodec/avpacket.c +++ b/libavcodec/avpacket.c @@ -26,12 +26,21 @@ void av_destruct_packet_nofree(AVPacket *pkt) { pkt->data = NULL; pkt->size = 0; + pkt->side_data = NULL; + pkt->side_data_elems = 0; } void av_destruct_packet(AVPacket *pkt) { + int i; + av_free(pkt->data); pkt->data = NULL; pkt->size = 0; + + for (i = 0; i < pkt->side_data_elems; i++) + av_free(pkt->side_data[i].data); + av_freep(&pkt->side_data); + pkt->side_data_elems = 0; } void av_init_packet(AVPacket *pkt) @@ -44,6 +53,8 @@ void av_init_packet(AVPacket *pkt) pkt->flags = 0; pkt->stream_index = 0; pkt->destruct= NULL; + pkt->side_data = NULL; + pkt->side_data_elems = 0; } int av_new_packet(AVPacket *pkt, int size) @@ -89,21 +100,40 @@ int av_grow_packet(AVPacket *pkt, int grow_by) return 0; } +#define DUP_DATA(dst, size, tmp, padding) \ + do { \ + if (padding) { \ + if ((unsigned)(size) > (unsigned)(size) + FF_INPUT_BUFFER_PADDING_SIZE) \ + return AVERROR(ENOMEM); \ + tmp = av_malloc(size + FF_INPUT_BUFFER_PADDING_SIZE); \ + } else { \ + tmp = av_malloc(size); \ + } \ + if (!data) \ + return AVERROR(ENOMEM); \ + memcpy(tmp, dst, size); \ + if (padding) \ + memset(tmp + size, 0, FF_INPUT_BUFFER_PADDING_SIZE); \ + dst = tmp; \ + } while(0) + int av_dup_packet(AVPacket *pkt) { if (((pkt->destruct == av_destruct_packet_nofree) || (pkt->destruct == NULL)) && pkt->data) { uint8_t *data; - /* 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); - data = av_malloc(pkt->size + FF_INPUT_BUFFER_PADDING_SIZE); - if (!data) { - return AVERROR(ENOMEM); - } - memcpy(data, pkt->data, pkt->size); - memset(data + pkt->size, 0, FF_INPUT_BUFFER_PADDING_SIZE); - pkt->data = data; + + DUP_DATA(pkt->data, pkt->size, data, 1); pkt->destruct = av_destruct_packet; + + if (pkt->side_data_elems) { + int i; + + DUP_DATA(pkt->side_data, pkt->side_data_elems * sizeof(*pkt->side_data), + data, 0); + for (i = 0; i < pkt->side_data_elems; i++) { + DUP_DATA(pkt->side_data[i].data, pkt->side_data[i].size, data, 1); + } + } } return 0; } @@ -113,5 +143,44 @@ 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_elems = 0; + } +} + +uint8_t* av_packet_new_side_data(AVPacket *pkt, int type, int size) +{ + int elems = pkt->side_data_elems; + + if ((unsigned)elems + 1 > INT_MAX / sizeof(*pkt->side_data)) + return NULL; + if ((unsigned)size > INT_MAX - FF_INPUT_BUFFER_PADDING_SIZE) + return NULL; + + pkt->side_data = av_realloc(pkt->side_data, (elems + 1) * sizeof(*pkt->side_data)); + if (!pkt->side_data) + return NULL; + + pkt->side_data[elems].data = av_malloc(size + FF_INPUT_BUFFER_PADDING_SIZE); + if (!pkt->side_data[elems].data) + return NULL; + pkt->side_data[elems].size = size; + pkt->side_data[elems].type = type; + pkt->side_data_elems++; + + return pkt->side_data[elems].data; +} + +uint8_t* av_packet_get_side_data(AVPacket *pkt, int type, int *size) +{ + int i; + + for (i = 0; i < pkt->side_data_elems; i++) { + if (pkt->side_data[i].type == type) { + if (size) + *size = pkt->side_data[i].size; + return pkt->side_data[i].data; + } } + return NULL; } diff --git a/libavcodec/version.h b/libavcodec/version.h index bad6509..4abdd5a 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 119 +#define LIBAVCODEC_VERSION_MINOR 120 #define LIBAVCODEC_VERSION_MICRO 0 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ -- 1.7.0.4
>From a71381768c3a1fd3836b0f9cbfa94b8179098679 Mon Sep 17 00:00:00 2001 From: Kostya Shishkov <[email protected]> Date: Sat, 9 Apr 2011 15:49:51 +0200 Subject: [PATCH 2/2] make containers pass palette change in AVPacket --- libavcodec/8bps.c | 21 +++++++++++---------- libavcodec/avcodec.h | 4 ++++ libavcodec/cinepak.c | 19 +++++++++++-------- libavcodec/idcinvideo.c | 12 ++++++------ libavcodec/interplayvideo.c | 21 ++++++++++----------- libavcodec/kmvc.c | 16 ++++++---------- libavcodec/msrle.c | 17 +++++++++-------- libavcodec/msvideo1.c | 24 +++++++++++++----------- libavcodec/qpeg.c | 12 +++++------- libavcodec/qtrle.c | 12 ++++++++---- libavcodec/rawdec.c | 10 +++++++--- libavcodec/smc.c | 13 ++++++++----- libavcodec/targa.c | 7 ------- libavcodec/tscc.c | 10 +++++++--- libavformat/asf.h | 2 ++ libavformat/asfdec.c | 21 +++++++++++++++------ libavformat/avidec.c | 24 +++++++++++------------- libavformat/idcin.c | 17 +++++++++++------ libavformat/ipmovie.c | 23 +++++++++++++++-------- libavformat/isom.h | 2 ++ libavformat/mov.c | 20 +++++++++++++++----- 21 files changed, 176 insertions(+), 131 deletions(-) diff --git a/libavcodec/8bps.c b/libavcodec/8bps.c index 1c6d406..055715f 100644 --- a/libavcodec/8bps.c +++ b/libavcodec/8bps.c @@ -50,6 +50,8 @@ typedef struct EightBpsContext { unsigned char planes; unsigned char planemap[4]; + + uint32_t pal[256]; } EightBpsContext; @@ -129,13 +131,16 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, AVPac } } - if (avctx->palctrl) { - memcpy (c->pic.data[1], avctx->palctrl->palette, AVPALETTE_SIZE); - if (avctx->palctrl->palette_changed) { + if (avctx->bits_per_coded_sample <= 8) { + const uint8_t *pal = av_packet_get_side_data(avpkt, + AV_PKT_DATA_PALETTE, + NULL); + if (pal) { c->pic.palette_has_changed = 1; - avctx->palctrl->palette_changed = 0; - } else - c->pic.palette_has_changed = 0; + memcpy(c->pal, pal, AVPALETTE_SIZE); + } + + memcpy (c->pic.data[1], c->pal, AVPALETTE_SIZE); } *data_size = sizeof(AVFrame); @@ -164,10 +169,6 @@ static av_cold int decode_init(AVCodecContext *avctx) avctx->pix_fmt = PIX_FMT_PAL8; c->planes = 1; c->planemap[0] = 0; // 1st plane is palette indexes - if (avctx->palctrl == NULL) { - av_log(avctx, AV_LOG_ERROR, "Error: PAL8 format but no palette from demuxer.\n"); - return -1; - } break; case 24: avctx->pix_fmt = avctx->get_format(avctx, pixfmt_rgb24); diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 3ae5ce4..6dc76e3 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -1100,6 +1100,10 @@ typedef struct AVPacket { #define PKT_FLAG_KEY AV_PKT_FLAG_KEY #endif +enum AVPacketSideDataType { + AV_PKT_DATA_PALETTE, +}; + /** * Audio Video Frame. * New fields can be added to the end of FF_COMMON_FRAME with minor version diff --git a/libavcodec/cinepak.c b/libavcodec/cinepak.c index f325bdb..4bda2a7 100644 --- a/libavcodec/cinepak.c +++ b/libavcodec/cinepak.c @@ -67,6 +67,7 @@ typedef struct CinepakContext { int sega_film_skip_bytes; + uint32_t pal[256]; } CinepakContext; static void cinepak_decode_codebook (cvid_codebook *codebook, @@ -395,7 +396,7 @@ static av_cold int cinepak_decode_init(AVCodecContext *avctx) s->sega_film_skip_bytes = -1; /* uninitialized state */ // check for paletted data - if ((avctx->palctrl == NULL) || (avctx->bits_per_coded_sample == 40)) { + if (avctx->bits_per_coded_sample != 8) { s->palette_video = 0; avctx->pix_fmt = PIX_FMT_YUV420P; } else { @@ -427,17 +428,19 @@ static int cinepak_decode_frame(AVCodecContext *avctx, return -1; } - cinepak_decode(s); - if (s->palette_video) { - memcpy (s->frame.data[1], avctx->palctrl->palette, AVPALETTE_SIZE); - if (avctx->palctrl->palette_changed) { + const uint8_t *pal = av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE, NULL); + if (pal) { s->frame.palette_has_changed = 1; - avctx->palctrl->palette_changed = 0; - } else - s->frame.palette_has_changed = 0; + memcpy(s->pal, pal, AVPALETTE_SIZE); + } } + cinepak_decode(s); + + if (s->palette_video) + memcpy (s->frame.data[1], s->pal, AVPALETTE_SIZE); + *data_size = sizeof(AVFrame); *(AVFrame*)data = s->frame; diff --git a/libavcodec/idcinvideo.c b/libavcodec/idcinvideo.c index b8d47ad..ac56e19 100644 --- a/libavcodec/idcinvideo.c +++ b/libavcodec/idcinvideo.c @@ -72,6 +72,7 @@ typedef struct IdcinContext { hnode huff_nodes[256][HUF_TOKENS*2]; int num_huff_nodes[256]; + uint32_t pal[256]; } IdcinContext; /* @@ -213,7 +214,7 @@ static int idcin_decode_frame(AVCodecContext *avctx, const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; IdcinContext *s = avctx->priv_data; - AVPaletteControl *palette_control = avctx->palctrl; + const uint8_t *pal = av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE, NULL); s->buf = buf; s->size = buf_size; @@ -228,13 +229,12 @@ static int idcin_decode_frame(AVCodecContext *avctx, idcin_decode_vlcs(s); - /* make the palette available on the way out */ - memcpy(s->frame.data[1], palette_control->palette, PALETTE_COUNT * 4); - /* If palette changed inform application*/ - if (palette_control->palette_changed) { - palette_control->palette_changed = 0; + if (pal) { s->frame.palette_has_changed = 1; + memcpy(s->pal, pal, AVPALETTE_SIZE); } + /* make the palette available on the way out */ + memcpy(s->frame.data[1], s->pal, AVPALETTE_SIZE); *data_size = sizeof(AVFrame); *(AVFrame*)data = s->frame; diff --git a/libavcodec/interplayvideo.c b/libavcodec/interplayvideo.c index 8dbe6f6..c12b241 100644 --- a/libavcodec/interplayvideo.c +++ b/libavcodec/interplayvideo.c @@ -77,6 +77,7 @@ typedef struct IpvideoContext { int stride; int upper_motion_limit_offset; + uint32_t pal[256]; } IpvideoContext; #define CHECK_STREAM_PTR(stream_ptr, stream_end, n) \ @@ -969,7 +970,7 @@ static void ipvideo_decode_opcodes(IpvideoContext *s) if (!s->is_16bpp) { /* this is PAL8, so make the palette available */ - memcpy(s->current_frame.data[1], s->avctx->palctrl->palette, PALETTE_COUNT * 4); + memcpy(s->current_frame.data[1], s->pal, AVPALETTE_SIZE); s->stride = s->current_frame.linesize[0]; s->stream_ptr = s->buf + 14; /* data starts 14 bytes in */ @@ -1023,10 +1024,6 @@ static av_cold int ipvideo_decode_init(AVCodecContext *avctx) s->is_16bpp = avctx->bits_per_coded_sample == 16; avctx->pix_fmt = s->is_16bpp ? PIX_FMT_RGB555 : PIX_FMT_PAL8; - if (!s->is_16bpp && s->avctx->palctrl == NULL) { - av_log(avctx, AV_LOG_ERROR, " Interplay video: palette expected.\n"); - return -1; - } dsputil_init(&s->dsp, avctx); @@ -1046,7 +1043,6 @@ static int ipvideo_decode_frame(AVCodecContext *avctx, const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; IpvideoContext *s = avctx->priv_data; - AVPaletteControl *palette_control = avctx->palctrl; /* compressed buffer needs to be large enough to at least hold an entire * decoding map */ @@ -1063,13 +1059,16 @@ static int ipvideo_decode_frame(AVCodecContext *avctx, return -1; } - ipvideo_decode_opcodes(s); - - if (!s->is_16bpp && palette_control->palette_changed) { - palette_control->palette_changed = 0; - s->current_frame.palette_has_changed = 1; + if (!s->is_16bpp) { + const uint8_t *pal = av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE, NULL); + if (pal) { + s->current_frame.palette_has_changed = 1; + memcpy(s->pal, pal, AVPALETTE_SIZE); + } } + ipvideo_decode_opcodes(s); + *data_size = sizeof(AVFrame); *(AVFrame*)data = s->current_frame; diff --git a/libavcodec/kmvc.c b/libavcodec/kmvc.c index 2671cc6..c41c882 100644 --- a/libavcodec/kmvc.c +++ b/libavcodec/kmvc.c @@ -233,6 +233,7 @@ static int decode_frame(AVCodecContext * avctx, void *data, int *data_size, AVPa int i; int header; int blocksize; + const uint8_t *pal = av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE, NULL); if (ctx->pic.data[0]) avctx->release_buffer(avctx, &ctx->pic); @@ -264,13 +265,6 @@ static int decode_frame(AVCodecContext * avctx, void *data, int *data_size, AVPa ctx->pic.pict_type = FF_P_TYPE; } - /* if palette has been changed, copy it from palctrl */ - if (ctx->avctx->palctrl && ctx->avctx->palctrl->palette_changed) { - memcpy(ctx->pal, ctx->avctx->palctrl->palette, AVPALETTE_SIZE); - ctx->setpal = 1; - ctx->avctx->palctrl->palette_changed = 0; - } - if (header & KMVC_PALETTE) { ctx->pic.palette_has_changed = 1; // palette starts from index 1 and has 127 entries @@ -279,6 +273,11 @@ static int decode_frame(AVCodecContext * avctx, void *data, int *data_size, AVPa } } + if (pal) { + ctx->pic.palette_has_changed = 1; + memcpy(ctx->pal, pal, AVPALETTE_SIZE); + } + if (ctx->setpal) { ctx->setpal = 0; ctx->pic.palette_has_changed = 1; @@ -374,9 +373,6 @@ static av_cold int decode_init(AVCodecContext * avctx) src += 4; } c->setpal = 1; - if (c->avctx->palctrl) { - c->avctx->palctrl->palette_changed = 0; - } } avctx->pix_fmt = PIX_FMT_PAL8; diff --git a/libavcodec/msrle.c b/libavcodec/msrle.c index a400589..f426b05 100644 --- a/libavcodec/msrle.c +++ b/libavcodec/msrle.c @@ -26,9 +26,6 @@ * http://www.pcisys.net/~melanson/codecs/ * * The MS RLE decoder outputs PAL8 colorspace data. - * - * Note that this decoder expects the palette colors from the end of the - * BITMAPINFO header passed through palctrl. */ #include <stdio.h> @@ -46,6 +43,7 @@ typedef struct MsrleContext { const unsigned char *buf; int size; + uint32_t pal[256]; } MsrleContext; static av_cold int msrle_decode_init(AVCodecContext *avctx) @@ -91,13 +89,16 @@ static int msrle_decode_frame(AVCodecContext *avctx, return -1; } - if (s->avctx->palctrl) { - /* make the palette available */ - memcpy(s->frame.data[1], s->avctx->palctrl->palette, AVPALETTE_SIZE); - if (s->avctx->palctrl->palette_changed) { + if (avctx->bits_per_coded_sample <= 8) { + const uint8_t *pal = av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE, NULL); + + if (pal) { s->frame.palette_has_changed = 1; - s->avctx->palctrl->palette_changed = 0; + memcpy(s->pal, pal, AVPALETTE_SIZE); } + + /* make the palette available */ + memcpy(s->frame.data[1], s->pal, AVPALETTE_SIZE); } /* FIXME how to correctly detect RLE ??? */ diff --git a/libavcodec/msvideo1.c b/libavcodec/msvideo1.c index e01ddf5..a89ec6a 100644 --- a/libavcodec/msvideo1.c +++ b/libavcodec/msvideo1.c @@ -25,9 +25,6 @@ * For more information about the MS Video-1 format, visit: * http://www.pcisys.net/~melanson/codecs/ * - * This decoder outputs either PAL8 or RGB555 data, depending on the - * whether a RGB palette was passed through palctrl; - * if it's present, then the data is PAL8; RGB555 otherwise. */ #include <stdio.h> @@ -55,6 +52,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) @@ -64,7 +62,7 @@ static av_cold int msvideo1_decode_init(AVCodecContext *avctx) s->avctx = avctx; /* figure out the colorspace based on the presence of a palette */ - if (s->avctx->palctrl) { + if (s->avctx->bits_per_coded_sample == 8) { s->mode_8bit = 1; avctx->pix_fmt = PIX_FMT_PAL8; } else { @@ -173,13 +171,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 +302,15 @@ static int msvideo1_decode_frame(AVCodecContext *avctx, return -1; } + if (s->mode_8bit) { + const uint8_t *pal = av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE, NULL); + + if (pal) { + memcpy(s->pal, pal, AVPALETTE_SIZE); + 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..c96184f 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, @@ -256,6 +257,7 @@ static int decode_frame(AVCodecContext *avctx, AVFrame * const p= (AVFrame*)&a->pic; uint8_t* outdata; int delta; + const uint8_t *pal = av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE, NULL); if(p->data[0]) avctx->release_buffer(avctx, p); @@ -274,11 +276,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 (pal) { a->pic.palette_has_changed = 1; - a->avctx->palctrl->palette_changed = 0; + memcpy(a->pal, pal, AVPALETTE_SIZE); } + memcpy(a->pic.data[1], a->pal, AVPALETTE_SIZE); *data_size = sizeof(AVFrame); *(AVFrame*)data = a->pic; @@ -289,10 +291,6 @@ static int decode_frame(AVCodecContext *avctx, static av_cold int decode_init(AVCodecContext *avctx){ QpegContext * const a = avctx->priv_data; - if (!avctx->palctrl) { - av_log(avctx, AV_LOG_FATAL, "Missing required palette via palctrl\n"); - return -1; - } a->avctx = avctx; avctx->pix_fmt= PIX_FMT_PAL8; a->refdata = av_malloc(avctx->width * avctx->height); diff --git a/libavcodec/qtrle.c b/libavcodec/qtrle.c index a8cc903..e14c306 100644 --- a/libavcodec/qtrle.c +++ b/libavcodec/qtrle.c @@ -46,6 +46,7 @@ typedef struct QtrleContext { const unsigned char *buf; int size; + uint32_t pal[256]; } QtrleContext; #define CHECK_STREAM_PTR(n) \ @@ -511,12 +512,15 @@ static int qtrle_decode_frame(AVCodecContext *avctx, } if(has_palette) { - /* make the palette available on the way out */ - memcpy(s->frame.data[1], s->avctx->palctrl->palette, AVPALETTE_SIZE); - if (s->avctx->palctrl->palette_changed) { + const uint8_t *pal = av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE, NULL); + + if (pal) { s->frame.palette_has_changed = 1; - s->avctx->palctrl->palette_changed = 0; + memcpy(s->pal, pal, AVPALETTE_SIZE); } + + /* make the palette available on the way out */ + memcpy(s->frame.data[1], s->pal, AVPALETTE_SIZE); } done: diff --git a/libavcodec/rawdec.c b/libavcodec/rawdec.c index 3c38829..3dbfdfe 100644 --- a/libavcodec/rawdec.c +++ b/libavcodec/rawdec.c @@ -158,9 +158,13 @@ static int raw_decode(AVCodecContext *avctx, (av_pix_fmt_descriptors[avctx->pix_fmt].flags & PIX_FMT_PAL))){ frame->data[1]= context->palette; } - if (avctx->palctrl && avctx->palctrl->palette_changed) { - memcpy(frame->data[1], avctx->palctrl->palette, AVPALETTE_SIZE); - avctx->palctrl->palette_changed = 0; + if (avctx->pix_fmt == PIX_FMT_PAL8) { + const uint8_t *pal = av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE, NULL); + + if (pal) { + memcpy(frame->data[1], pal, AVPALETTE_SIZE); + frame->palette_has_changed = 1; + } } if(avctx->pix_fmt==PIX_FMT_BGR24 && ((frame->linesize[0]+3)&~3)*avctx->height <= buf_size) frame->linesize[0] = (frame->linesize[0]+3)&~3; diff --git a/libavcodec/smc.c b/libavcodec/smc.c index fe92b43..e75203d 100644 --- a/libavcodec/smc.c +++ b/libavcodec/smc.c @@ -54,6 +54,7 @@ typedef struct SmcContext { unsigned char color_quads[COLORS_PER_TABLE * CQUAD]; unsigned char color_octets[COLORS_PER_TABLE * COCTET]; + uint32_t pal[256]; } SmcContext; #define GET_BLOCK_COUNT() \ @@ -110,11 +111,7 @@ static void smc_decode_stream(SmcContext *s) int color_octet_index = 0; /* 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->pal, AVPALETTE_SIZE); chunk_size = AV_RB32(&s->buf[stream_ptr]) & 0x00FFFFFF; stream_ptr += 4; @@ -440,6 +437,7 @@ static int smc_decode_frame(AVCodecContext *avctx, const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; SmcContext *s = avctx->priv_data; + const uint8_t *pal = av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE, NULL); s->buf = buf; s->size = buf_size; @@ -452,6 +450,11 @@ static int smc_decode_frame(AVCodecContext *avctx, return -1; } + if (pal) { + s->frame.palette_has_changed = 1; + memcpy(s->pal, pal, AVPALETTE_SIZE); + } + smc_decode_stream(s); *data_size = sizeof(AVFrame); diff --git a/libavcodec/targa.c b/libavcodec/targa.c index 06f87e4..910cc1b 100644 --- a/libavcodec/targa.c +++ b/libavcodec/targa.c @@ -171,13 +171,6 @@ static int decode_frame(AVCodecContext *avctx, stride = -p->linesize[0]; } - if(avctx->pix_fmt == PIX_FMT_PAL8 && avctx->palctrl){ - memcpy(p->data[1], avctx->palctrl->palette, AVPALETTE_SIZE); - if(avctx->palctrl->palette_changed){ - p->palette_has_changed = 1; - avctx->palctrl->palette_changed = 0; - } - } if(colors){ size_t pal_size; if((colors + first_clr) > 256){ diff --git a/libavcodec/tscc.c b/libavcodec/tscc.c index f695973..bd05f02 100644 --- a/libavcodec/tscc.c +++ b/libavcodec/tscc.c @@ -60,6 +60,8 @@ typedef struct TsccContext { unsigned char* decomp_buf; int height; z_stream zstream; + + uint32_t pal[256]; } CamtasiaContext; /* @@ -111,11 +113,13 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, AVPac /* make the palette available on the way out */ if (c->avctx->pix_fmt == PIX_FMT_PAL8) { - memcpy(c->pic.data[1], c->avctx->palctrl->palette, AVPALETTE_SIZE); - if (c->avctx->palctrl->palette_changed) { + const uint8_t *pal = av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE, NULL); + + if (pal) { c->pic.palette_has_changed = 1; - c->avctx->palctrl->palette_changed = 0; + memcpy(c->pal, pal, AVPALETTE_SIZE); } + memcpy(c->pic.data[1], c->pal, AVPALETTE_SIZE); } *data_size = sizeof(AVFrame); diff --git a/libavformat/asf.h b/libavformat/asf.h index b563459..b72445d 100644 --- a/libavformat/asf.h +++ b/libavformat/asf.h @@ -44,6 +44,8 @@ typedef struct { uint16_t stream_language_index; + int palette_changed; + uint32_t palette[256]; } ASFStream; typedef uint8_t ff_asf_guid[16]; diff --git a/libavformat/asfdec.c b/libavformat/asfdec.c index 57e8fb6..3bd8dc6 100644 --- a/libavformat/asfdec.c +++ b/libavformat/asfdec.c @@ -363,15 +363,14 @@ static int asf_read_stream_properties(AVFormatContext *s, int64_t size) /* This is true for all paletted codecs implemented in ffmpeg */ if (st->codec->extradata_size && (st->codec->bits_per_coded_sample <= 8)) { int av_unused i; - st->codec->palctrl = av_mallocz(sizeof(AVPaletteControl)); #if HAVE_BIGENDIAN for (i = 0; i < FFMIN(st->codec->extradata_size, AVPALETTE_SIZE)/4; i++) - st->codec->palctrl->palette[i] = av_bswap32(((uint32_t*)st->codec->extradata)[i]); + asf_st->palette[i] = av_bswap32(((uint32_t*)st->codec->extradata)[i]); #else - memcpy(st->codec->palctrl->palette, st->codec->extradata, - FFMIN(st->codec->extradata_size, AVPALETTE_SIZE)); + memcpy(asf_st->palette, st->codec->extradata, + FFMIN(st->codec->extradata_size, AVPALETTE_SIZE)); #endif - st->codec->palctrl->palette_changed = 1; + asf_st->palette_changed = 1; } st->codec->codec_tag = tag1; @@ -964,6 +963,17 @@ static int ff_asf_parse_packet(AVFormatContext *s, AVIOContext *pb, AVPacket *pk asf_st->pkt.stream_index = asf->stream_index; asf_st->pkt.pos = asf_st->packet_pos= asf->packet_pos; + if (asf_st->pkt.data && asf_st->palette_changed) { + uint8_t *pal; + pal = av_packet_new_side_data(pkt, AV_PKT_DATA_PALETTE, + AVPALETTE_SIZE); + if (!pal) { + av_log(s, AV_LOG_ERROR, "Cannot append palette to packet\n"); + } else { + memcpy(pal, asf_st->palette, AVPALETTE_SIZE); + asf_st->palette_changed = 0; + } + } //printf("new packet: stream:%d key:%d packet_key:%d audio:%d size:%d\n", //asf->stream_index, asf->packet_key_frame, asf_st->pkt.flags & AV_PKT_FLAG_KEY, //s->streams[asf->stream_index]->codec->codec_type == AVMEDIA_TYPE_AUDIO, asf->packet_obj_size); @@ -1125,7 +1135,6 @@ static int asf_read_close(AVFormatContext *s) asf_reset_header(s); for(i=0;i<s->nb_streams;i++) { AVStream *st = s->streams[i]; - av_free(st->codec->palctrl); } return 0; } diff --git a/libavformat/avidec.c b/libavformat/avidec.c index ae8d320..86596c3 100644 --- a/libavformat/avidec.c +++ b/libavformat/avidec.c @@ -589,15 +589,14 @@ static int avi_read_header(AVFormatContext *s, AVFormatParameters *ap) /* This code assumes that extradata contains only palette. */ /* This is true for all paletted codecs implemented in FFmpeg. */ if (st->codec->extradata_size && (st->codec->bits_per_coded_sample <= 8)) { - st->codec->palctrl = av_mallocz(sizeof(AVPaletteControl)); #if HAVE_BIGENDIAN for (i = 0; i < FFMIN(st->codec->extradata_size, AVPALETTE_SIZE)/4; i++) - st->codec->palctrl->palette[i] = av_bswap32(((uint32_t*)st->codec->extradata)[i]); + ast->pal[i] = av_bswap32(((uint32_t*)st->codec->extradata)[i]); #else - memcpy(st->codec->palctrl->palette, st->codec->extradata, + memcpy(ast->pal, st->codec->extradata, FFMIN(st->codec->extradata_size, AVPALETTE_SIZE)); #endif - st->codec->palctrl->palette_changed = 1; + ast->has_pal = 1; } print_tag("video", tag1, 0); @@ -929,14 +928,14 @@ 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"); + uint8_t *pal; + pal = av_packet_new_side_data(pkt, AV_PKT_DATA_PALETTE, AVPALETTE_SIZE); + if(!pal){ + av_log(s, AV_LOG_ERROR, "Failed to allocate data for palette\n"); + }else{ + memcpy(pal, ast->pal, AVPALETTE_SIZE); + ast->has_pal = 0; + } } if (CONFIG_DV_DEMUXER && avi->dv_demux) { @@ -1337,7 +1336,6 @@ static int avi_read_close(AVFormatContext *s) for(i=0;i<s->nb_streams;i++) { AVStream *st = s->streams[i]; AVIStream *ast = st->priv_data; - av_free(st->codec->palctrl); if (ast) { if (ast->sub_ctx) { av_freep(&ast->sub_ctx->pb); diff --git a/libavformat/idcin.c b/libavformat/idcin.c index e6883c7..04ae687 100644 --- a/libavformat/idcin.c +++ b/libavformat/idcin.c @@ -86,8 +86,6 @@ typedef struct IdcinDemuxContext { int audio_present; int64_t pts; - - AVPaletteControl palctrl; } IdcinDemuxContext; static int idcin_probe(AVProbeData *p) @@ -172,8 +170,6 @@ static int idcin_read_header(AVFormatContext *s, if (avio_read(pb, st->codec->extradata, HUFFMAN_TABLE_SIZE) != HUFFMAN_TABLE_SIZE) return AVERROR(EIO); - /* save a reference in order to transport the palette */ - st->codec->palctrl = &idcin->palctrl; /* if sample rate is 0, assume no audio */ if (sample_rate) { @@ -226,6 +222,7 @@ static int idcin_read_packet(AVFormatContext *s, int palette_scale; unsigned char r, g, b; unsigned char palette_buffer[768]; + uint32_t palette[256]; if (s->pb->eof_reached) return AVERROR(EIO); @@ -236,7 +233,6 @@ static int idcin_read_packet(AVFormatContext *s, return AVERROR(EIO); } else if (command == 1) { /* trigger a palette change */ - idcin->palctrl.palette_changed = 1; if (avio_read(pb, palette_buffer, 768) != 768) return AVERROR(EIO); /* scale the palette as necessary */ @@ -251,7 +247,7 @@ static int idcin_read_packet(AVFormatContext *s, r = palette_buffer[i * 3 ] << palette_scale; g = palette_buffer[i * 3 + 1] << palette_scale; b = palette_buffer[i * 3 + 2] << palette_scale; - idcin->palctrl.palette[i] = (r << 16) | (g << 8) | (b); + palette[i] = (r << 16) | (g << 8) | (b); } } @@ -262,6 +258,15 @@ static int idcin_read_packet(AVFormatContext *s, ret= av_get_packet(pb, pkt, chunk_size); if (ret < 0) return ret; + if (command == 1) { + uint8_t *pal; + + pal = av_packet_new_side_data(pkt, AV_PKT_DATA_PALETTE, + AVPALETTE_SIZE); + if (ret < 0) + return ret; + memcpy(pal, palette, AVPALETTE_SIZE); + } pkt->stream_index = idcin->video_stream_index; pkt->pts = idcin->pts; } else { diff --git a/libavformat/ipmovie.c b/libavformat/ipmovie.c index e1d08df..e3215d3 100644 --- a/libavformat/ipmovie.c +++ b/libavformat/ipmovie.c @@ -97,6 +97,8 @@ typedef struct IPMVEContext { unsigned int video_width; unsigned int video_height; int64_t video_pts; + uint32_t palette[256]; + int has_palette; unsigned int audio_bits; unsigned int audio_channels; @@ -116,8 +118,6 @@ typedef struct IPMVEContext { int64_t next_chunk_offset; - AVPaletteControl palette_control; - } IPMVEContext; static int load_ipmovie_packet(IPMVEContext *s, AVIOContext *pb, @@ -162,6 +162,17 @@ static int load_ipmovie_packet(IPMVEContext *s, AVIOContext *pb, if (av_new_packet(pkt, s->decode_map_chunk_size + s->video_chunk_size)) return CHUNK_NOMEM; + if (s->has_palette) { + uint8_t *pal; + + pal = av_packet_new_side_data(pkt, AV_PKT_DATA_PALETTE, + AVPALETTE_SIZE); + if (pal) { + memcpy(pal, s->palette, AVPALETTE_SIZE); + s->has_palette = 0; + } + } + pkt->pos= s->decode_map_chunk_offset; avio_seek(pb, s->decode_map_chunk_offset, SEEK_SET); s->decode_map_chunk_offset = 0; @@ -456,10 +467,9 @@ static int process_ipmovie_chunk(IPMVEContext *s, AVIOContext *pb, 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; + s->has_palette = 1; break; case OPCODE_SET_PALETTE_COMPRESSED: @@ -573,9 +583,6 @@ static int ipmovie_read_header(AVFormatContext *s, st->codec->height = ipmovie->video_height; st->codec->bits_per_coded_sample = ipmovie->video_bpp; - /* palette considerations */ - st->codec->palctrl = &ipmovie->palette_control; - if (ipmovie->audio_type) { st = av_new_stream(s, 0); if (!st) diff --git a/libavformat/isom.h b/libavformat/isom.h index fba4963..48e0bcf 100644 --- a/libavformat/isom.h +++ b/libavformat/isom.h @@ -123,6 +123,8 @@ typedef struct MOVStreamContext { int width; ///< tkhd width int height; ///< tkhd height int dts_shift; ///< dts shift when ctts is negative + uint32_t palette[256]; + int has_palette; } MOVStreamContext; typedef struct MOVContext { diff --git a/libavformat/mov.c b/libavformat/mov.c index 61ceaac..bd8cf03 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -1027,7 +1027,6 @@ int ff_mov_read_stsd_entries(MOVContext *c, AVIOContext *pb, int entries) unsigned int color_start, color_count, color_end; unsigned char r, g, b; - st->codec->palctrl = av_malloc(sizeof(*st->codec->palctrl)); if (color_greyscale) { int color_index, color_dec; /* compute the greyscale palette */ @@ -1037,7 +1036,7 @@ int ff_mov_read_stsd_entries(MOVContext *c, AVIOContext *pb, int entries) color_dec = 256 / (color_count - 1); for (j = 0; j < color_count; j++) { r = g = b = color_index; - st->codec->palctrl->palette[j] = + sc->palette[j] = (r << 16) | (g << 8) | (b); color_index -= color_dec; if (color_index < 0) @@ -1058,7 +1057,7 @@ int ff_mov_read_stsd_entries(MOVContext *c, AVIOContext *pb, int entries) r = color_table[j * 3 + 0]; g = color_table[j * 3 + 1]; b = color_table[j * 3 + 2]; - st->codec->palctrl->palette[j] = + sc->palette[j] = (r << 16) | (g << 8) | (b); } } else { @@ -1080,12 +1079,12 @@ int ff_mov_read_stsd_entries(MOVContext *c, AVIOContext *pb, int entries) avio_r8(pb); b = avio_r8(pb); avio_r8(pb); - st->codec->palctrl->palette[j] = + sc->palette[j] = (r << 16) | (g << 8) | (b); } } } - st->codec->palctrl->palette_changed = 1; + sc->has_palette = 1; } } else if(st->codec->codec_type==AVMEDIA_TYPE_AUDIO) { int bits_per_sample, flags; @@ -2433,6 +2432,17 @@ static int mov_read_packet(AVFormatContext *s, AVPacket *pkt) ret = av_get_packet(sc->pb, pkt, sample->size); if (ret < 0) return ret; + if (sc->has_palette) { + uint8_t *pal; + + pal = av_packet_new_side_data(pkt, AV_PKT_DATA_PALETTE, AVPALETTE_SIZE); + if (!pal) { + av_log(mov->fc, AV_LOG_ERROR, "Cannot append palette to packet\n"); + } else { + memcpy(pal, sc->palette, AVPALETTE_SIZE); + sc->has_palette = 0; + } + } #if CONFIG_DV_DEMUXER if (mov->dv_demux && sc->dv_audio_container) { dv_produce_packet(mov->dv_demux, pkt, pkt->data, pkt->size); -- 1.7.0.4
_______________________________________________ libav-devel mailing list [email protected] https://lists.libav.org/mailman/listinfo/libav-devel
