diff --git a/Changelog b/Changelog index a40f32c23f..b972302beb 100644 --- a/Changelog +++ b/Changelog @@ -3,6 +3,7 @@ releases are sorted from youngest to oldest. version : - libaribcaption decoder +- Playdate video decoder version 6.0: - Radiance HDR image support diff --git a/configure b/configure index 033db7442d..549ed1401c 100755 --- a/configure +++ b/configure @@ -2899,6 +2899,7 @@ notchlc_decoder_select="lzf" nuv_decoder_select="idctdsp" opus_decoder_deps="swresample" opus_encoder_select="audio_frame_queue" +pdv_decoder_deps="zlib" png_decoder_select="inflate_wrapper" png_encoder_select="deflate_wrapper llvidencdsp" prores_decoder_select="blockdsp idctdsp" diff --git a/libavcodec/Makefile b/libavcodec/Makefile index aa10fbfcf8..a1a8b8b88e 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -583,6 +583,7 @@ OBJS-$(CONFIG_PBM_DECODER) += pnmdec.o pnm.o OBJS-$(CONFIG_PBM_ENCODER) += pnmenc.o OBJS-$(CONFIG_PCX_DECODER) += pcx.o OBJS-$(CONFIG_PCX_ENCODER) += pcxenc.o +OBJS-$(CONFIG_PDV_DECODER) += pdvdec.o OBJS-$(CONFIG_PFM_DECODER) += pnmdec.o pnm.o OBJS-$(CONFIG_PFM_ENCODER) += pnmenc.o OBJS-$(CONFIG_PGM_DECODER) += pnmdec.o pnm.o diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index 797fe39486..8eeed34e57 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -251,6 +251,7 @@ extern const FFCodec ff_pbm_encoder; extern const FFCodec ff_pbm_decoder; extern const FFCodec ff_pcx_encoder; extern const FFCodec ff_pcx_decoder; +extern const FFCodec ff_pdv_decoder; extern const FFCodec ff_pfm_encoder; extern const FFCodec ff_pfm_decoder; extern const FFCodec ff_pgm_encoder; diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c index efdcb59bc9..d40977d6b3 100644 --- a/libavcodec/codec_desc.c +++ b/libavcodec/codec_desc.c @@ -1923,6 +1923,13 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("ViewQuest VQC"), .props = AV_CODEC_PROP_LOSSY, }, + { + .id = AV_CODEC_ID_PDV, + .type = AVMEDIA_TYPE_VIDEO, + .name = "pdv", + .long_name = NULL_IF_CONFIG_SMALL("PDV (PlayDate Video)"), + .props = AV_CODEC_PROP_LOSSY, + }, /* various PCM "codecs" */ { diff --git a/libavcodec/codec_id.h b/libavcodec/codec_id.h index 64df9699f4..70800ec20b 100644 --- a/libavcodec/codec_id.h +++ b/libavcodec/codec_id.h @@ -320,6 +320,7 @@ enum AVCodecID { AV_CODEC_ID_WBMP, AV_CODEC_ID_MEDIA100, AV_CODEC_ID_VQC, + AV_CODEC_ID_PDV, /* various PCM "codecs" */ AV_CODEC_ID_FIRST_AUDIO = 0x10000, ///< A dummy id pointing at the start of audio codecs diff --git a/libavcodec/pdvdec.c b/libavcodec/pdvdec.c new file mode 100644 index 0000000000..690a298e16 --- /dev/null +++ b/libavcodec/pdvdec.c @@ -0,0 +1,127 @@ +/* + * PDV video format + * + * Copyright (c) 2023 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 "codec_internal.h" +#include "decode.h" +#include "zlib_wrapper.h" + +#include + +typedef struct PDVContext { + AVFrame *previous_frame; + FFZStream zstream; +} PDVContext; + +static av_cold int decode_init(AVCodecContext *avctx) +{ + PDVContext *s = avctx->priv_data; + + avctx->pix_fmt = AV_PIX_FMT_MONOBLACK; + + s->previous_frame = av_frame_alloc(); + if (!s->previous_frame) + return AVERROR(ENOMEM); + + return ff_inflate_init(&s->zstream, avctx); +} + +static av_cold int decode_end(AVCodecContext *avctx) +{ + PDVContext *s = avctx->priv_data; + + av_frame_free(&s->previous_frame); + ff_inflate_end(&s->zstream); + + return 0; +} + +static int decode_frame(AVCodecContext *avctx, AVFrame *frame, + int *got_frame, AVPacket *avpkt) +{ + PDVContext *s = avctx->priv_data; + AVFrame *prev_frame = s->previous_frame; + z_stream *const zstream = &s->zstream.zstream; + uint8_t *dst, *prev = prev_frame->data[0]; + int ret, zret; + + zret = inflateReset(zstream); + if (zret != Z_OK) { + av_log(avctx, AV_LOG_ERROR, "Could not reset inflate: %d.\n", zret); + return AVERROR_INVALIDDATA; + } + + if ((ret = ff_get_buffer(avctx, frame, AV_GET_BUFFER_FLAG_REF)) < 0) + return ret; + + zstream->next_in = avpkt->data; + zstream->avail_in = avpkt->size; + + dst = frame->data[0]; + for (int i = 0; i < avctx->height; i++) { + zstream->next_out = dst; + zstream->avail_out = (avctx->width + 7) >> 3; + + zret = inflate(zstream, Z_SYNC_FLUSH); + if (zret != Z_OK && zret != Z_STREAM_END) { + av_log(avctx, AV_LOG_ERROR, + "Inflate failed with return code: %d.\n", zret); + return AVERROR_INVALIDDATA; + } + + if (!(avpkt->flags & AV_PKT_FLAG_KEY)) { + for (int j = 0; j < (avctx->width + 7) >> 3; j++) + dst[j] ^= prev[j]; + prev += prev_frame->linesize[0]; + } + + dst += frame->linesize[0]; + } + + av_frame_unref(s->previous_frame); + if ((ret = av_frame_ref(s->previous_frame, frame)) < 0) + return ret; + + if (avpkt->flags & AV_PKT_FLAG_KEY) { + frame->key_frame = 1; + frame->pict_type = AV_PICTURE_TYPE_I; + } else { + frame->pict_type = AV_PICTURE_TYPE_P; + } + + *got_frame = 1; + + return avpkt->size; +} + +const FFCodec ff_pdv_decoder = { + .p.name = "pdv", + CODEC_LONG_NAME("PDV (PlayDate Video)"), + .priv_data_size = sizeof(PDVContext), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_PDV, + .p.capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM, + .init = decode_init, + .close = decode_end, + FF_CODEC_DECODE_CB(decode_frame), +}; diff --git a/libavcodec/version.h b/libavcodec/version.h index 230d5fa13e..80e2ae630d 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -29,7 +29,7 @@ #include "version_major.h" -#define LIBAVCODEC_VERSION_MINOR 9 +#define LIBAVCODEC_VERSION_MINOR 10 #define LIBAVCODEC_VERSION_MICRO 100 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \