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
