From c9ec824211cccb745b3a4ab014d6be726c8ef1b9 Mon Sep 17 00:00:00 2001
From: Paul B Mahol <onemda@gmail.com>
Date: Tue, 31 Jan 2023 10:18:17 +0100
Subject: [PATCH] avcodec: add media100_to_mjpegb bitstream filter and use it
Signed-off-by: Paul B Mahol <onemda@gmail.com>
---
libavcodec/Makefile | 3 +-
libavcodec/bitstream_filters.c | 1 +
.../{media100.c => media100_to_mjpegb_bsf.c} | 112 +++++++-----------
libavcodec/mjpegbdec.c | 15 +++
4 files changed, 61 insertions(+), 70 deletions(-)
rename libavcodec/{media100.c => media100_to_mjpegb_bsf.c} (65%)
@@ -485,7 +485,7 @@ OBJS-$(CONFIG_MACE6_DECODER) += mace.o
OBJS-$(CONFIG_MAGICYUV_DECODER) += magicyuv.o
OBJS-$(CONFIG_MAGICYUV_ENCODER) += magicyuvenc.o
OBJS-$(CONFIG_MDEC_DECODER) += mdec.o mpeg12.o mpeg12data.o
-OBJS-$(CONFIG_MEDIA100_DECODER) += media100.o
+OBJS-$(CONFIG_MEDIA100_DECODER) += mjpegbdec.o
OBJS-$(CONFIG_METASOUND_DECODER) += metasound.o twinvq.o
OBJS-$(CONFIG_MICRODVD_DECODER) += microdvddec.o ass.o
OBJS-$(CONFIG_MIMIC_DECODER) += mimic.o
@@ -1221,6 +1221,7 @@ OBJS-$(CONFIG_HEVC_METADATA_BSF) += h265_metadata_bsf.o h265_profile_le
h2645data.o
OBJS-$(CONFIG_HEVC_MP4TOANNEXB_BSF) += hevc_mp4toannexb_bsf.o
OBJS-$(CONFIG_IMX_DUMP_HEADER_BSF) += imx_dump_header_bsf.o
+OBJS-$(CONFIG_MEDIA100_TO_MJPEGB_BSF) += media100_to_mjpegb_bsf.o
OBJS-$(CONFIG_MJPEG2JPEG_BSF) += mjpeg2jpeg_bsf.o
OBJS-$(CONFIG_MJPEGA_DUMP_HEADER_BSF) += mjpega_dump_header_bsf.o
OBJS-$(CONFIG_MPEG4_UNPACK_BFRAMES_BSF) += mpeg4_unpack_bframes_bsf.o
@@ -43,6 +43,7 @@ extern const FFBitStreamFilter ff_hapqa_extract_bsf;
extern const FFBitStreamFilter ff_hevc_metadata_bsf;
extern const FFBitStreamFilter ff_hevc_mp4toannexb_bsf;
extern const FFBitStreamFilter ff_imx_dump_header_bsf;
+extern const FFBitStreamFilter ff_media100_to_mjpegb_bsf;
extern const FFBitStreamFilter ff_mjpeg2jpeg_bsf;
extern const FFBitStreamFilter ff_mjpega_dump_header_bsf;
extern const FFBitStreamFilter ff_mp3_header_decompress_bsf;
similarity index 65%
rename from libavcodec/media100.c
rename to libavcodec/media100_to_mjpegb_bsf.c
@@ -1,6 +1,6 @@
/*
- * Media 100 decoder
- * Copyright (c) 2022 Paul B Mahol
+ * Media 100 to MJPEGB bitstream filter
+ * Copyright (c) 2023 Paul B Mahol
*
* This file is part of FFmpeg.
*
@@ -21,55 +21,34 @@
/**
* @file
- * Media 100 decoder.
+ * Media 100 to MJPEGB bitstream filter.
*/
#include <inttypes.h>
+#include "bsf.h"
+#include "bsf_internal.h"
#include "libavutil/intreadwrite.h"
-#include "avcodec.h"
#include "bytestream.h"
-#include "codec_internal.h"
typedef struct Media100Context {
- AVCodecContext *avctx; // wrapper context for mjpegb
AVPacket *pkt;
} Media100Context;
-static av_cold int media100_decode_init(AVCodecContext *avctx)
+static av_cold int init(AVBSFContext *ctx)
{
- Media100Context *ctx = avctx->priv_data;
- const AVCodec *codec;
- int ret;
-
- codec = avcodec_find_decoder(AV_CODEC_ID_MJPEGB);
- if (!codec)
- return AVERROR_BUG;
- ctx->avctx = avcodec_alloc_context3(codec);
- if (!ctx->avctx)
- return AVERROR(ENOMEM);
- ctx->avctx->thread_count = 1;
- ctx->avctx->flags = avctx->flags;
- ctx->avctx->flags2 = avctx->flags2;
- ctx->avctx->width = ctx->avctx->coded_width = avctx->width;
- ctx->avctx->height = ctx->avctx->coded_height = avctx->height;
-
- ret = avcodec_open2(ctx->avctx, codec, NULL);
- if (ret < 0)
- return ret;
+ Media100Context *s = ctx->priv_data;
- ctx->pkt = av_packet_alloc();
- if (!ctx->pkt)
+ s->pkt = av_packet_alloc();
+ if (!s->pkt)
return AVERROR(ENOMEM);
return 0;
}
-static int media100_decode_frame(AVCodecContext *avctx,
- AVFrame *frame, int *got_frame,
- AVPacket *avpkt)
+static int filter(AVBSFContext *ctx, AVPacket *avpkt)
{
- Media100Context *ctx = avctx->priv_data;
+ Media100Context *s = ctx->priv_data;
unsigned second_field_offset = 0;
unsigned next_field = 0;
unsigned dht_offset[2];
@@ -83,18 +62,20 @@ static int media100_decode_frame(AVCodecContext *avctx,
AVPacket *pkt;
int ret;
- if (avpkt->size + 1024 > ctx->pkt->size) {
- ret = av_grow_packet(ctx->pkt, avpkt->size + 1024 - ctx->pkt->size);
- if (ret < 0)
- return ret;
- }
+ ret = ff_bsf_get_packet_ref(ctx, avpkt);
+ if (ret < 0)
+ return ret;
- ret = av_packet_make_writable(ctx->pkt);
+ ret = av_new_packet(s->pkt, avpkt->size + 1024);
+ if (ret < 0)
+ return ret;
+
+ ret = av_packet_make_writable(s->pkt);
if (ret < 0)
return ret;
bytestream2_init(&gb, avpkt->data, avpkt->size);
- bytestream2_init_writer(&pb, ctx->pkt->data, ctx->pkt->size);
+ bytestream2_init_writer(&pb, s->pkt->data, s->pkt->size);
second_field:
bytestream2_put_be32(&pb, 0);
@@ -107,8 +88,8 @@ second_field:
sof_offset[field] = bytestream2_tell_p(&pb);
bytestream2_put_be16(&pb, 17);
bytestream2_put_byte(&pb, 8);
- bytestream2_put_be16(&pb, avctx->height / 2);
- bytestream2_put_be16(&pb, avctx->width);
+ bytestream2_put_be16(&pb, ctx->par_in->height / 2);
+ bytestream2_put_be16(&pb, ctx->par_in->width);
bytestream2_put_byte(&pb, 3);
bytestream2_put_byte(&pb, 1);
bytestream2_put_byte(&pb, 0x21);
@@ -164,7 +145,7 @@ second_field:
goto second_field;
}
- pkt = ctx->pkt;
+ pkt = s->pkt;
AV_WB32(pkt->data + 8, second_field_offset);
AV_WB32(pkt->data + 12, second_field_offset);
@@ -186,40 +167,33 @@ second_field:
pkt->size = bytestream2_tell_p(&pb);
- ret = avcodec_send_packet(ctx->avctx, pkt);
- if (ret < 0) {
- av_log(avctx, AV_LOG_ERROR, "Error submitting a packet for decoding\n");
- return ret;
- }
+ av_packet_copy_props(pkt, avpkt);
+ av_packet_unref(avpkt);
+ av_packet_move_ref(avpkt, s->pkt);
- ret = avcodec_receive_frame(ctx->avctx, frame);
- if (ret < 0)
- return ret;
+ return 0;
+}
- avctx->pix_fmt = ctx->avctx->pix_fmt;
- *got_frame = 1;
+static void flush(AVBSFContext *ctx)
+{
+ Media100Context *s = ctx->priv_data;
- return avpkt->size;
+ av_packet_unref(s->pkt);
}
-static av_cold int media100_decode_end(AVCodecContext *avctx)
+static av_cold void uninit(AVBSFContext *ctx)
{
- Media100Context *ctx = avctx->priv_data;
+ Media100Context *s = ctx->priv_data;
- avcodec_free_context(&ctx->avctx);
- av_packet_free(&ctx->pkt);
-
- return 0;
+ av_packet_free(&s->pkt);
}
-const FFCodec ff_media100_decoder = {
- .p.name = "media100",
- CODEC_LONG_NAME("Media 100"),
- .p.type = AVMEDIA_TYPE_VIDEO,
- .p.id = AV_CODEC_ID_MEDIA100,
- .priv_data_size = sizeof(Media100Context),
- .init = media100_decode_init,
- .close = media100_decode_end,
- FF_CODEC_DECODE_CB(media100_decode_frame),
- .caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
+const FFBitStreamFilter ff_media100_to_mjpegb_bsf = {
+ .p.name = "media100_to_mjpegb",
+ .p.codec_ids = (const enum AVCodecID []){ AV_CODEC_ID_MEDIA100, AV_CODEC_ID_NONE },
+ .priv_data_size = sizeof(Media100Context),
+ .init = init,
+ .flush = flush,
+ .close = uninit,
+ .filter = filter,
};
@@ -168,3 +168,18 @@ const FFCodec ff_mjpegb_decoder = {
.p.max_lowres = 3,
.caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
};
+
+const FFCodec ff_media100_decoder = {
+ .p.name = "media100",
+ CODEC_LONG_NAME("Media 100"),
+ .p.type = AVMEDIA_TYPE_VIDEO,
+ .p.id = AV_CODEC_ID_MEDIA100,
+ .priv_data_size = sizeof(MJpegDecodeContext),
+ .init = ff_mjpeg_decode_init,
+ .close = ff_mjpeg_decode_end,
+ FF_CODEC_DECODE_CB(mjpegb_decode_frame),
+ .p.capabilities = AV_CODEC_CAP_DR1,
+ .p.max_lowres = 3,
+ .caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
+ .bsfs = "media100_to_mjpegb",
+};
--
2.39.1