On 7/15/2019 6:20 PM, Paul B Mahol wrote: > Signed-off-by: Paul B Mahol <one...@gmail.com> > --- > configure | 1 + > libavcodec/Makefile | 1 + > libavcodec/allcodecs.c | 1 + > libavcodec/avcodec.h | 1 + > libavcodec/codec_desc.c | 7 ++ > libavcodec/imm5.c | 234 ++++++++++++++++++++++++++++++++++++++++ > libavformat/riff.c | 1 + > 7 files changed, 246 insertions(+) > create mode 100644 libavcodec/imm5.c > > diff --git a/configure b/configure > index 5a4f507246..d03cf43350 100755 > --- a/configure > +++ b/configure > @@ -2714,6 +2714,7 @@ huffyuv_encoder_select="bswapdsp huffman huffyuvencdsp > llvidencdsp" > hymt_decoder_select="huffyuv_decoder" > iac_decoder_select="imc_decoder" > imc_decoder_select="bswapdsp fft mdct sinewin" > +imm5_decoder_select="h264_decoder hevc_decoder" > indeo3_decoder_select="hpeldsp" > indeo4_decoder_select="ividsp" > indeo5_decoder_select="ividsp" > diff --git a/libavcodec/Makefile b/libavcodec/Makefile > index 3cd73fbcc6..39f4d9118c 100644 > --- a/libavcodec/Makefile > +++ b/libavcodec/Makefile > @@ -393,6 +393,7 @@ OBJS-$(CONFIG_IFF_ILBM_DECODER) += iff.o > OBJS-$(CONFIG_ILBC_DECODER) += ilbcdec.o > OBJS-$(CONFIG_IMC_DECODER) += imc.o > OBJS-$(CONFIG_IMM4_DECODER) += imm4.o > +OBJS-$(CONFIG_IMM5_DECODER) += imm5.o > OBJS-$(CONFIG_INDEO2_DECODER) += indeo2.o > OBJS-$(CONFIG_INDEO3_DECODER) += indeo3.o > OBJS-$(CONFIG_INDEO4_DECODER) += indeo4.o ivi.o > diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c > index d2f9a39ce5..fe7f773925 100644 > --- a/libavcodec/allcodecs.c > +++ b/libavcodec/allcodecs.c > @@ -158,6 +158,7 @@ extern AVCodec ff_hymt_decoder; > extern AVCodec ff_idcin_decoder; > extern AVCodec ff_iff_ilbm_decoder; > extern AVCodec ff_imm4_decoder; > +extern AVCodec ff_imm5_decoder; > extern AVCodec ff_indeo2_decoder; > extern AVCodec ff_indeo3_decoder; > extern AVCodec ff_indeo4_decoder; > diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h > index 2528bd89ab..da6f92b443 100644 > --- a/libavcodec/avcodec.h > +++ b/libavcodec/avcodec.h > @@ -457,6 +457,7 @@ enum AVCodecID { > AV_CODEC_ID_AGM, > AV_CODEC_ID_LSCR, > AV_CODEC_ID_VP4, > + AV_CODEC_ID_IMM5, > > /* various PCM "codecs" */ > AV_CODEC_ID_FIRST_AUDIO = 0x10000, ///< A dummy id pointing at the > start of audio codecs > diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c > index 4d033c20ff..e6373be504 100644 > --- a/libavcodec/codec_desc.c > +++ b/libavcodec/codec_desc.c > @@ -1726,6 +1726,13 @@ static const AVCodecDescriptor codec_descriptors[] = { > .long_name = NULL_IF_CONFIG_SMALL("On2 VP4"), > .props = AV_CODEC_PROP_LOSSY, > }, > + { > + .id = AV_CODEC_ID_IMM5, > + .type = AVMEDIA_TYPE_VIDEO, > + .name = "imm5", > + .long_name = NULL_IF_CONFIG_SMALL("Infinity IMM5"), > + .props = AV_CODEC_PROP_LOSSY, > + }, > > /* various PCM "codecs" */ > { > diff --git a/libavcodec/imm5.c b/libavcodec/imm5.c > new file mode 100644 > index 0000000000..f6b2ce691c > --- /dev/null > +++ b/libavcodec/imm5.c > @@ -0,0 +1,234 @@ > +/* > + * Copyright (c) 2019 Paul B Mahol > + * > + * This file is part of FFmpeg. > + * > + * FFmpeg is free software; you can redistribute it and/or > + * modify it under the terms of the GNU Lesser General Public > + * License as published by the Free Software Foundation; either > + * version 2.1 of the License, or (at your option) any later version. > + * > + * FFmpeg is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + * Lesser General Public License for more details. > + * > + * You should have received a copy of the GNU Lesser General Public > + * License along with FFmpeg; if not, write to the Free Software > + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 > USA > + */ > + > +#include "avcodec.h" > +#include "bytestream.h" > +#include "internal.h" > + > +typedef struct IMM5Context { > + AVCodecContext *h264_avctx; // wrapper context for H264 > + AVCodecContext *hevc_avctx; // wrapper context for HEVC > + > + int width, height; > + GetByteContext gbc; > + > + uint8_t *imm5_buffer; > + int imm5_buffer_size; > +} IMM5Context; > + > +static const struct IMM5_unit { > + uint8_t bits[14]; > + uint8_t len; > +} IMM5_units[14] = { > + { { 0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0x80, 0x1E, 0xF4, 0x0B, 0x0F, > 0x88 }, 12 }, > + { { 0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0x80, 0x1E, 0xF4, 0x05, 0x83, > 0xE2 }, 12 }, > + { { 0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0x80, 0x1E, 0xF4, 0x05, 0x81, > 0xE8, 0x80 }, 13 }, > + { { 0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0x80, 0x1E, 0xF4, 0x0B, 0x04, > 0xA2 }, 12 }, > + { { 0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0x80, 0x1E, 0xF4, 0x05, 0x81, > 0x28, 0x80 }, 13 }, > + { { 0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0x80, 0x1E, 0xF4, 0x05, 0x80, > 0x92, 0x20 }, 13 }, > + { { 0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0x00, 0x1E, 0x9A, 0x74, 0x0B, > 0x0F, 0xC8 }, 13 }, > + { { 0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0x00, 0x1E, 0x9A, 0x74, 0x05, > 0x83, 0xF2 }, 13 }, > + { { 0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0x00, 0x1E, 0x9A, 0x74, 0x05, > 0x81, 0xEC, 0x80 }, 14 }, > + { { 0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0x00, 0x1E, 0x9A, 0x74, 0x0B, > 0x04, 0xB2 }, 13 }, > + { { 0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0x00, 0x1E, 0x9A, 0x74, 0x05, > 0x81, 0x2C, 0x80 }, 14 }, > + { { 0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0x00, 0x1E, 0x9A, 0x74, 0x05, > 0x80, 0x93, 0x20 }, 14 }, > + { { 0x00, 0x00, 0x00, 0x01, 0x68, 0xDE, 0x3C, 0x80 }, 8 }, > + { { 0x00, 0x00, 0x00, 0x01, 0x68, 0xCE, 0x32, 0x28 }, 8 }, > +}; > + > +static av_cold int imm5_init(AVCodecContext *avctx) > +{ > + IMM5Context *ctx = avctx->priv_data; > + const AVCodec *codec; > + int ret; > + > + codec = avcodec_find_decoder(AV_CODEC_ID_H264); > + if (!codec) > + return AVERROR_BUG; > + ctx->h264_avctx = avcodec_alloc_context3(codec); > + if (!ctx->h264_avctx) > + return AVERROR(ENOMEM); > + ctx->h264_avctx->flags = avctx->flags; > + ctx->h264_avctx->flags2 = avctx->flags2; > + ret = ff_codec_open2_recursive(ctx->h264_avctx, codec, NULL); > + if (ret < 0) > + return ret; > + > + codec = avcodec_find_decoder(AV_CODEC_ID_HEVC); > + if (!codec) > + return AVERROR_BUG; > + ctx->hevc_avctx = avcodec_alloc_context3(codec); > + if (!ctx->hevc_avctx) > + return AVERROR(ENOMEM); > + ctx->hevc_avctx->flags = avctx->flags; > + ctx->hevc_avctx->flags2 = avctx->flags2; > + ret = ff_codec_open2_recursive(ctx->hevc_avctx, codec, NULL); > + if (ret < 0) > + return ret; > +
No passing AVOptions? You're opening the h264/hevc decoders with defaults, ignoring things like requested threads and similar. > + return 0; > +} > + > +static int imm5_decode_frame(AVCodecContext *avctx, void *data, > + int *got_frame, AVPacket *avpkt) > +{ > + IMM5Context *ctx = avctx->priv_data; > + AVFrame *frame; > + AVCodecContext *codec_avctx = ctx->h264_avctx; > + int buf_size = avpkt->size; > + uint8_t *buf = avpkt->data; > + AVPacket hpkt; > + int ret; > + > + if (avpkt->size > 24 && avpkt->data[8] <= 1 && AV_RL32(avpkt->data + 4) > < avpkt->size) { > + int codec_type = avpkt->data[1]; > + int index = avpkt->data[10]; > + int new_size = AV_RL32(avpkt->data + 4); > + int height, width, offset; > + > + if (codec_type == 0xA) > + codec_avctx = ctx->hevc_avctx; > + > + switch (index) { > + case 1: > + width = 352; > + height = 240; > + break; > + case 2: > + height = 240; > + width = 704; > + break; > + case 4: > + case 132: > + height = 480; > + width = 704; > + break; > + case 17: > + width = 352; > + height = 288; > + break; > + case 18: > + height = 288; > + width = 704; > + index = codec_type ? 11 : 5; > + break; > + case 133: > + width = 640; > + height = 480; > + break; > + case 134: > + width = 720; > + height = 480; > + break; > + case 135: > + width = 720; > + height = 576; > + break; > + case 136: > + width = 800; > + height = 600; > + break; > + case 137: > + width = 1024; > + height = 768; > + break; > + case 138: > + width = 1280; > + height = 1024; > + break; > + case 139: > + width = 1600; > + height = 1200; > + break; > + default: > + height = 576; > + width = 704; > + break; > + } Most of this stuff isn't unused. > + > + if (index >= 1 && index <= 12) { > + index -= 1; > + av_fast_padded_malloc(&ctx->imm5_buffer, &ctx->imm5_buffer_size, > buf_size); > + memcpy(ctx->imm5_buffer, IMM5_units[index].bits, > IMM5_units[index].len); > + offset = IMM5_units[index].len; > + if (avpkt->data[1] == 2) { > + memcpy(ctx->imm5_buffer + offset, IMM5_units[12].bits, > IMM5_units[12].len); > + offset += IMM5_units[12].len; > + } else { > + memcpy(ctx->imm5_buffer + offset, IMM5_units[13].bits, > IMM5_units[13].len); > + offset += IMM5_units[13].len; > + } > + memcpy(ctx->imm5_buffer + offset, avpkt->data + 24, new_size); > + buf = ctx->imm5_buffer; > + buf_size = new_size + offset; > + } else { > + buf += 24; > + buf_size -= 24; > + } > + } > + > + frame = av_frame_alloc(); > + > + av_init_packet(&hpkt); > + hpkt.data = buf; > + hpkt.size = buf_size; av_packet_copy_props() to preserve pts/dts? > + > + ret = avcodec_send_packet(codec_avctx, &hpkt); > + if (ret < 0) { > + av_log(avctx, AV_LOG_ERROR, "Error submitting a packet for > decoding\n"); > + return ret; > + } As others pointed on IRC, you can use avpkt directly if there was no need to use imm5_buffer, or when the "index >= 1 && index <= 12" check didn't succeed (in which case you just apply that offset to avpkt's fields). > + > + ret = avcodec_receive_frame(codec_avctx, frame); > + if (ret < 0) > + return ret; > + > + avctx->pix_fmt = codec_avctx->pix_fmt; > + ret = av_frame_ref(data, frame); > + if (ret < 0) > + return ret; You're leaking both the frame and the AVFrame object. Why not just pass data instead? > + > + *got_frame = 1; > + > + return avpkt->size; > +} > + > +static av_cold int imm5_close(AVCodecContext *avctx) > +{ > + IMM5Context *ctx = avctx->priv_data; > + > + avcodec_free_context(&ctx->h264_avctx); > + avcodec_free_context(&ctx->hevc_avctx); > + > + return 0; > +} > + > +AVCodec ff_imm5_decoder = { > + .name = "imm5", > + .long_name = NULL_IF_CONFIG_SMALL("Infinity IMM5"), > + .type = AVMEDIA_TYPE_VIDEO, > + .id = AV_CODEC_ID_IMM5, > + .init = imm5_init, > + .decode = imm5_decode_frame, > + .close = imm5_close, > + .priv_data_size = sizeof(IMM5Context), > + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | > + FF_CODEC_CAP_INIT_CLEANUP, > +}; > diff --git a/libavformat/riff.c b/libavformat/riff.c > index e755ad8d5f..610974ebf0 100644 > --- a/libavformat/riff.c > +++ b/libavformat/riff.c > @@ -488,6 +488,7 @@ const AVCodecTag ff_codec_bmp_tags[] = { > { AV_CODEC_ID_AGM, MKTAG('A', 'G', 'M', '6') }, > { AV_CODEC_ID_AGM, MKTAG('A', 'G', 'M', '7') }, > { AV_CODEC_ID_LSCR, MKTAG('L', 'S', 'C', 'R') }, > + { AV_CODEC_ID_IMM5, MKTAG('I', 'M', 'M', '5') }, And this is in turn encapsulated in AVI? Lovely... > { AV_CODEC_ID_NONE, 0 } > }; > > _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".