This is an automated email from the git hooks/post-receive script. Git pushed a commit to branch master in repository ffmpeg.
commit 7905079bef56b67198be178a369a719826e67cd5 Author: Lynne <[email protected]> AuthorDate: Thu Oct 8 13:27:47 2026 +0900 Commit: Lynne <[email protected]> CommitDate: Thu Oct 8 14:21:37 2026 +0900 lavc: add a Panasonic RW2 parser Reads IFD0 from the first chunk to set the dimensions and pixel format, so that probing fills in the stream parameters without decoding a frame. --- libavcodec/Makefile | 1 + libavcodec/parsers.c | 1 + libavcodec/rw2_parser.c | 126 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 128 insertions(+) diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 93d526ee56..3d2200af8c 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -1309,6 +1309,7 @@ OBJS-$(CONFIG_PRORES_RAW_PARSER) += prores_raw_parser.o OBJS-$(CONFIG_QOI_PARSER) += qoi_parser.o OBJS-$(CONFIG_PRORES_PARSER) += prores_parser.o OBJS-$(CONFIG_RV34_PARSER) += rv34_parser.o +OBJS-$(CONFIG_RW2_PARSER) += rw2_parser.o OBJS-$(CONFIG_SBC_PARSER) += sbc_parser.o OBJS-$(CONFIG_SIPR_PARSER) += sipr_parser.o OBJS-$(CONFIG_TAK_PARSER) += tak_parser.o tak.o diff --git a/libavcodec/parsers.c b/libavcodec/parsers.c index b54442a0ea..263b606407 100644 --- a/libavcodec/parsers.c +++ b/libavcodec/parsers.c @@ -76,6 +76,7 @@ extern const FFCodecParser ff_pnm_parser; extern const FFCodecParser ff_prores_raw_parser; extern const FFCodecParser ff_qoi_parser; extern const FFCodecParser ff_rv34_parser; +extern const FFCodecParser ff_rw2_parser; extern const FFCodecParser ff_sbc_parser; extern const FFCodecParser ff_sipr_parser; extern const FFCodecParser ff_tak_parser; diff --git a/libavcodec/rw2_parser.c b/libavcodec/rw2_parser.c new file mode 100644 index 0000000000..00c0ce81d0 --- /dev/null +++ b/libavcodec/rw2_parser.c @@ -0,0 +1,126 @@ +/* + * Panasonic RW2 parser + * Copyright (c) 2026 Lynne <[email protected]> + * + * 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 + */ + +/* + * Delimits frames on the "IIU\0" magic and reads IFD0 to set the dimensions + * and pixel format without decoding. + */ + +#include "libavutil/common.h" +#include "libavutil/intreadwrite.h" + +#include "parser.h" +#include "parser_internal.h" + +typedef struct RW2ParseContext { + ParseContext pc; +} RW2ParseContext; + +static void rw2_set_params(AVCodecParserContext *s, AVCodecContext *avctx, + const uint8_t *buf, int buf_size) +{ + static const enum AVPixelFormat cfa_fmts[] = { + AV_PIX_FMT_BAYER_RGGB16, AV_PIX_FMT_BAYER_GRBG16, + AV_PIX_FMT_BAYER_GBRG16, AV_PIX_FMT_BAYER_BGGR16, + }; + + if (buf_size < 8 || AV_RL32(buf) != MKTAG('I', 'I', 'U', 0)) + return; + + int64_t ifd = AV_RL32(buf + 4); + if (ifd < 8 || ifd + 2 > buf_size) + return; + + int width = 0, height = 0, cfa = 0, bpp = 0; + int n = FFMIN(AV_RL16(buf + ifd), (buf_size - ifd - 2) / 12); + for (int i = 0; i < n; i++) { + const uint8_t *e = buf + ifd + 2 + 12*i; + unsigned tag = AV_RL16(e), type = AV_RL16(e + 2), val = AV_RL32(e + 8); + unsigned v = type == 3 ? val & 0xFFFF : val; + + switch (tag) { + case 0x02: width = v; break; + case 0x03: height = v; break; + case 0x09: cfa = v; break; + case 0x0A: bpp = v; break; + } + } + + if (width > 0 && height > 0 && cfa >= 1 && cfa <= 4) { + s->width = width; + s->height = height; + s->format = cfa_fmts[cfa - 1]; + avctx->color_trc = AVCOL_TRC_LINEAR; + if (bpp >= 8 && bpp <= 16) + avctx->bits_per_raw_sample = bpp; + } +} + +static int rw2_parse(AVCodecParserContext *s, AVCodecContext *avctx, + const uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size) +{ + RW2ParseContext *ipc = s->priv_data; + uint32_t state = ipc->pc.state; + int next = END_NOT_FOUND; + + s->key_frame = 1; + s->pict_type = AV_PICTURE_TYPE_I; + + /* The header lands in the first chunk, so the parameters are known without + * waiting for, or decoding, the whole frame */ + if (buf_size >= 8 && AV_RL32(buf) == MKTAG('I', 'I', 'U', 0)) + rw2_set_params(s, avctx, buf, buf_size); + + if (s->flags & PARSER_FLAG_COMPLETE_FRAMES) { + next = buf_size; + } else { + for (int i = 0; i < buf_size; i++) { + state = (state << 8) | buf[i]; + if (state == MKBETAG('I', 'I', 'U', 0)) { + /* The next frame's magic ends this one */ + if (ipc->pc.frame_start_found) { + next = i - 3; + ipc->pc.frame_start_found = 0; + break; + } + ipc->pc.frame_start_found = 1; + } + } + ipc->pc.state = state; + if (ff_combine_frame(&ipc->pc, next, &buf, &buf_size) < 0) { + *poutbuf = NULL; + *poutbuf_size = 0; + return buf_size; + } + } + + *poutbuf = buf; + *poutbuf_size = buf_size; + return next; +} + +const FFCodecParser ff_rw2_parser = { + PARSER_CODEC_LIST(AV_CODEC_ID_RW2), + .priv_data_size = sizeof(RW2ParseContext), + .parse = rw2_parse, + .close = ff_parse_close, +}; -- To stop receiving notification emails like this one, please contact [email protected]. _______________________________________________ ffmpeg-cvslog mailing list -- [email protected] To unsubscribe send an email to [email protected]
