* [FFmpeg-devel] [PATCH 1/3] avcodec: add AV_CODEC_ID_BRAW
@ 2025-04-15 10:04 Lynne
2025-04-15 10:04 ` [FFmpeg-devel] [PATCH 2/3] lavf/mov: support demuxing Blackmagic RAW streams Lynne
2025-04-15 10:04 ` [FFmpeg-devel] [PATCH 3/3] avcodec: add Blackmagic RAW decoder Lynne
0 siblings, 2 replies; 4+ messages in thread
From: Lynne @ 2025-04-15 10:04 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Lynne
This adds codec entries for the Blackmagic RAW codec.
---
libavcodec/codec_desc.c | 7 +++++++
libavcodec/codec_id.h | 1 +
2 files changed, 8 insertions(+)
diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c
index 9fb190e35a..90e31a8b6a 100644
--- a/libavcodec/codec_desc.c
+++ b/libavcodec/codec_desc.c
@@ -1985,6 +1985,13 @@ static const AVCodecDescriptor codec_descriptors[] = {
.props = AV_CODEC_PROP_LOSSY | AV_CODEC_PROP_LOSSLESS,
.mime_types= MT("image/jxl"),
},
+ {
+ .id = AV_CODEC_ID_BRAW,
+ .type = AVMEDIA_TYPE_VIDEO,
+ .name = "braw",
+ .long_name = NULL_IF_CONFIG_SMALL("Blackmagic RAW"),
+ .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY,
+ },
/* various PCM "codecs" */
{
diff --git a/libavcodec/codec_id.h b/libavcodec/codec_id.h
index 2f6efe8261..0175fc2d7b 100644
--- a/libavcodec/codec_id.h
+++ b/libavcodec/codec_id.h
@@ -329,6 +329,7 @@ enum AVCodecID {
AV_CODEC_ID_DNXUC,
AV_CODEC_ID_RV60,
AV_CODEC_ID_JPEGXL_ANIM,
+ AV_CODEC_ID_BRAW,
/* various PCM "codecs" */
AV_CODEC_ID_FIRST_AUDIO = 0x10000, ///< A dummy id pointing at the start of audio codecs
--
2.49.0.395.g12beb8f557c
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 4+ messages in thread
* [FFmpeg-devel] [PATCH 2/3] lavf/mov: support demuxing Blackmagic RAW streams
2025-04-15 10:04 [FFmpeg-devel] [PATCH 1/3] avcodec: add AV_CODEC_ID_BRAW Lynne
@ 2025-04-15 10:04 ` Lynne
2025-04-15 10:04 ` [FFmpeg-devel] [PATCH 3/3] avcodec: add Blackmagic RAW decoder Lynne
1 sibling, 0 replies; 4+ messages in thread
From: Lynne @ 2025-04-15 10:04 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Lynne
---
libavformat/isom_tags.c | 7 +++++++
libavformat/mov.c | 2 +-
2 files changed, 8 insertions(+), 1 deletion(-)
diff --git a/libavformat/isom_tags.c b/libavformat/isom_tags.c
index f05762beec..7bf2bf7d5b 100644
--- a/libavformat/isom_tags.c
+++ b/libavformat/isom_tags.c
@@ -286,6 +286,13 @@ const AVCodecTag ff_codec_movvideo_tags[] = {
{ AV_CODEC_ID_RAWVIDEO, MKTAG('B', 'G', 'G', 'R') }, /* ASC Bayer BGGR */
+ { AV_CODEC_ID_BRAW, MKTAG('b', 'r', 'x', 'q') }, /* Blackmagic RAW */
+ { AV_CODEC_ID_BRAW, MKTAG('b', 'r', 'h', 'q') },
+ { AV_CODEC_ID_BRAW, MKTAG('b', 'r', 's', 't') },
+ { AV_CODEC_ID_BRAW, MKTAG('b', 'r', 'l', 't') },
+ { AV_CODEC_ID_BRAW, MKTAG('b', 'r', 'v', 'l') },
+ { AV_CODEC_ID_BRAW, MKTAG('b', 'r', 'v', 'm') },
+
{ AV_CODEC_ID_MEDIA100, MKTAG('6', '0', '1', 'N') },
{ AV_CODEC_ID_MEDIA100, MKTAG('6', '0', '1', 'P') },
{ AV_CODEC_ID_MEDIA100, MKTAG('d', 't', 'n', 't') },
diff --git a/libavformat/mov.c b/libavformat/mov.c
index 452690090c..b4056fba48 100644
--- a/libavformat/mov.c
+++ b/libavformat/mov.c
@@ -11349,7 +11349,7 @@ const FFInputFormat ff_mov_demuxer = {
.p.name = "mov,mp4,m4a,3gp,3g2,mj2",
.p.long_name = NULL_IF_CONFIG_SMALL("QuickTime / MOV"),
.p.priv_class = &mov_class,
- .p.extensions = "mov,mp4,m4a,3gp,3g2,mj2,psp,m4b,ism,ismv,isma,f4v,avif,heic,heif",
+ .p.extensions = "mov,mp4,m4a,3gp,3g2,mj2,psp,m4b,ism,ismv,isma,f4v,avif,heic,heif,braw",
.p.flags = AVFMT_NO_BYTE_SEEK | AVFMT_SEEK_TO_PTS | AVFMT_SHOW_IDS,
.priv_data_size = sizeof(MOVContext),
.flags_internal = FF_INFMT_FLAG_INIT_CLEANUP,
--
2.49.0.395.g12beb8f557c
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 4+ messages in thread
* [FFmpeg-devel] [PATCH 3/3] avcodec: add Blackmagic RAW decoder
2025-04-15 10:04 [FFmpeg-devel] [PATCH 1/3] avcodec: add AV_CODEC_ID_BRAW Lynne
2025-04-15 10:04 ` [FFmpeg-devel] [PATCH 2/3] lavf/mov: support demuxing Blackmagic RAW streams Lynne
@ 2025-04-15 10:04 ` Lynne
2025-04-15 12:07 ` Lynne
1 sibling, 1 reply; 4+ messages in thread
From: Lynne @ 2025-04-15 10:04 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Lynne
Most of the work was done by Paul B Mahol.
I cleaned the patch up, improved the code a bit, and added slice
threading.
---
configure | 1 +
libavcodec/Makefile | 1 +
libavcodec/allcodecs.c | 1 +
libavcodec/braw.c | 666 +++++++++++++++++++++++++++++++++++++++++
4 files changed, 669 insertions(+)
create mode 100755 libavcodec/braw.c
diff --git a/configure b/configure
index bd4f872376..1171260d57 100755
--- a/configure
+++ b/configure
@@ -2943,6 +2943,7 @@ av1_decoder_select="atsc_a53 cbs_av1 dovi_rpudec"
bink_decoder_select="blockdsp hpeldsp"
binkaudio_dct_decoder_select="wma_freqs"
binkaudio_rdft_decoder_select="wma_freqs"
+braw_decoder_select="idctdsp"
cavs_decoder_select="blockdsp golomb h264chroma idctdsp qpeldsp videodsp"
clearvideo_decoder_select="idctdsp"
cllc_decoder_select="bswapdsp"
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index 7bd1dbec9a..50733ab048 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -289,6 +289,7 @@ OBJS-$(CONFIG_BMP_ENCODER) += bmpenc.o
OBJS-$(CONFIG_BMV_AUDIO_DECODER) += bmvaudio.o
OBJS-$(CONFIG_BMV_VIDEO_DECODER) += bmvvideo.o
OBJS-$(CONFIG_BONK_DECODER) += bonk.o
+OBJS-$(CONFIG_BRAW_DECODER) += braw.o
OBJS-$(CONFIG_BRENDER_PIX_DECODER) += brenderpix.o
OBJS-$(CONFIG_C93_DECODER) += c93.o
OBJS-$(CONFIG_CAVS_DECODER) += cavs.o cavsdec.o cavsdsp.o \
diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
index f10519617e..277e17acc3 100644
--- a/libavcodec/allcodecs.c
+++ b/libavcodec/allcodecs.c
@@ -69,6 +69,7 @@ extern const FFCodec ff_bitpacked_encoder;
extern const FFCodec ff_bmp_encoder;
extern const FFCodec ff_bmp_decoder;
extern const FFCodec ff_bmv_video_decoder;
+extern const FFCodec ff_braw_decoder;
extern const FFCodec ff_brender_pix_decoder;
extern const FFCodec ff_c93_decoder;
extern const FFCodec ff_cavs_decoder;
diff --git a/libavcodec/braw.c b/libavcodec/braw.c
new file mode 100755
index 0000000000..2246b2d645
--- /dev/null
+++ b/libavcodec/braw.c
@@ -0,0 +1,666 @@
+/*
+ * Blackmagic RAW codec
+ *
+ * Copyright (c) 2019 Paul B Mahol
+ * Copyright (c) 2025 Lynne
+ *
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "libavutil/mem_internal.h"
+
+#include "decode.h"
+#include "thread.h"
+#include "codec_internal.h"
+#include "mpegvideo.h"
+#include "bytestream.h"
+#include "get_bits.h"
+#include "vlc.h"
+#include "simple_idct.h"
+
+#define IN_IDCT_DEPTH 16
+#define PRORES_ONLY
+#define BIT_DEPTH 12
+#include "simple_idct_template.c"
+
+#define BRAW_MAX_TILES 1024
+
+typedef struct BRAWTile {
+ const uint8_t *data;
+ uint32_t size;
+ int x;
+ int y;
+ int blocks_w_in_tile;
+ int blocks_h_in_tile;
+ int ret;
+} BRAWTile;
+
+typedef struct BRAWContext {
+ const AVClass *class;
+
+ enum AVPixelFormat pix_fmt;
+
+ GetByteContext gb;
+
+ uint32_t header_size;
+
+ int offsets[4][2];
+
+ int nb_tiles_w;
+ int nb_tiles_h;
+ int tile_size_w[256];
+ int tile_offset_w[257];
+ int tile_size_h;
+
+ int qscale[3];
+ int quant[2][64];
+
+ ScanTable scan;
+ IDCTDSPContext idsp;
+
+ BRAWTile tiles[BRAW_MAX_TILES];
+ AVFrame *frame;
+} BRAWContext;
+
+static const uint16_t dc_codes[16] = {
+ 0x0, 0x2, 0x3, 0x4, 0x5, 0x6, 0x1C, 0x1D, 0x3E, 0xFF4, 0xFF5, 0xFF7, 0xFED, 0x1E, 0xFFE, 0x1FFE,
+};
+static const uint8_t dc_bits[16] = {
+ 2, 3, 3, 3, 3, 3, 5, 5, 6, 12, 12, 12, 12, 5, 12, 13,
+};
+
+static const uint32_t ac_codes[194] = {
+ 0x000000, 0x000001, 0x000004, 0x00000B, 0x00000C, 0x00000A,
+ 0x00001A, 0x00001B, 0x00001C, 0x00003A, 0x00003B, 0x000078,
+ 0x000079, 0x00007A, 0x00007B, 0x0000F8, 0x0000F9, 0x0000FA,
+ 0x0001F6, 0x0001F7, 0x0001F8, 0x0001F9, 0x0001FA, 0x0003F6,
+ 0x0003F7, 0x0003F8, 0x0003F9, 0x0003FA, 0x0007F8, 0x0007F9,
+ 0x000FED, 0x000FF4, 0x000FF5, 0x000FF7, 0x000FEC, 0x000FF6,
+ 0x001FDC, 0x001FDD, 0x001FDE, 0x001FDF, 0x007FC0, 0x00FF84,
+ 0x00FF85, 0x00FF86, 0x00FF87, 0x00FF88, 0x00FF89, 0x00FF8A,
+ 0x00FF8B, 0x00FF8C, 0x00FF8D, 0x00FF8E, 0x00FF8F, 0x00FF90,
+ 0x00FF91, 0x00FF92, 0x00FF93, 0x00FF94, 0x00FF95, 0x00FF96,
+ 0x00FF97, 0x00FF98, 0x00FF99, 0x00FF9A, 0x00FF9B, 0x00FF9C,
+ 0x00FF9D, 0x00FF9E, 0x00FF9F, 0x00FFA0, 0x00FFA1, 0x00FFA2,
+ 0x00FFA3, 0x00FFA4, 0x00FFA5, 0x00FFA6, 0x00FFA7, 0x00FFA8,
+ 0x00FFA9, 0x00FFAA, 0x00FFAB, 0x00FFAC, 0x00FFAE, 0x00FFAF,
+ 0x00FFB0, 0x00FFB1, 0x00FFB2, 0x00FFB3, 0x00FFB4, 0x00FFB6,
+ 0x00FFB7, 0x00FFB8, 0x00FFB9, 0x00FFBA, 0x00FFBB, 0x00FFBC,
+ 0x00FFBE, 0x00FFBF, 0x00FFC0, 0x00FFC1, 0x00FFC2, 0x00FFC3,
+ 0x00FFC4, 0x00FFC5, 0x00FFC7, 0x00FFC8, 0x00FFC9, 0x00FFCA,
+ 0x00FFCB, 0x00FFCC, 0x00FFCD, 0x00FFCE, 0x00FFD0, 0x00FFD1,
+ 0x00FFD2, 0x00FFD3, 0x00FFD4, 0x00FFD5, 0x00FFD6, 0x00FFD7,
+ 0x00FFD9, 0x00FFDA, 0x00FFDB, 0x00FFDC, 0x00FFDD, 0x00FFDE,
+ 0x00FFDF, 0x00FFE0, 0x00FFE2, 0x00FFE3, 0x00FFE4, 0x00FFE5,
+ 0x00FFE6, 0x00FFE7, 0x00FFE8, 0x00FFE9, 0x00FFEB, 0x00FFEC,
+ 0x00FFED, 0x00FFEE, 0x00FFEF, 0x00FFF0, 0x00FFF1, 0x00FFF2,
+ 0x00FFF3, 0x00FFF5, 0x00FFF6, 0x00FFF7, 0x00FFF8, 0x00FFF9,
+ 0x00FFFA, 0x00FFFB, 0x00FFFC, 0x00FFFD, 0x03FEB5, 0x03FEB6,
+ 0x03FEB7, 0x03FED5, 0x03FED6, 0x03FED7, 0x03FEF5, 0x03FEF6,
+ 0x03FEF7, 0x03FF19, 0x03FEB4, 0x03FF1A, 0x03FF1B, 0x03FED4,
+ 0x03FF3D, 0x03FF3E, 0x03FEF4, 0x03FF3F, 0x03FF61, 0x03FF18,
+ 0x03FF62, 0x03FF63, 0x03FF3C, 0x03FF85, 0x03FF86, 0x03FF60,
+ 0x03FF87, 0x03FFA9, 0x03FF84, 0x03FFAA, 0x03FFAB, 0x03FFA8,
+ 0x03FFD1, 0x03FFD2, 0x03FFD0, 0x03FFD3, 0x03FFF9, 0x03FFF8,
+ 0x03FFFA, 0x03FFFB,
+};
+static const uint8_t ac_bits[194] = {
+ 2, 2, 3, 4, 4, 4, 5, 5, 5, 6, 6, 7, 7, 7, 7, 8, 8, 8, 9, 9, 9, 9, 9, 10, 10,
+ 10, 10, 10, 11, 11, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 15, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 18, 18, 18, 18,
+ 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
+ 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
+};
+
+#define DC_VLC_BITS 13
+#define AC_VLC_BITS 18
+static VLCElem dc_vlc[1 << DC_VLC_BITS];
+static VLCElem ac_vlc[1 << AC_VLC_BITS];
+
+static av_cold void braw_static_init(void)
+{
+ VLC_INIT_STATIC_TABLE(dc_vlc, DC_VLC_BITS, FF_ARRAY_ELEMS(dc_bits), dc_bits, 1, 1, dc_codes, 2, 2, 0);
+ VLC_INIT_STATIC_TABLE(ac_vlc, AC_VLC_BITS, FF_ARRAY_ELEMS(ac_bits), ac_bits, 1, 1, ac_codes, 4, 4, 0);
+}
+
+static inline void idct4ColPut_int16_12bit(uint16_t *dest, ptrdiff_t line_size, int16_t *in)
+{
+ const int X0 = 17734;
+ const int X1 = 42813;
+ const int X2 = 32768;
+ int a0 = (in[8*0] * X2);
+ int a2 = (in[8*2] * X2);
+ int a1 = in[8*1];
+ int a3 = in[8*3];
+ int c0 = a0 + a2;
+ int c1 = a0 - a2;
+ int c2 = a1 * X0 - a3 * X1;
+ int c3 = a3 * X0 + a1 * X1;
+ int d0 = av_clip_uintp2((c0 + c3) >> 16, 12);
+ int d1 = av_clip_uintp2((c1 + c2) >> 16, 12);
+ int d2 = av_clip_uintp2((c1 - c2) >> 16, 12);
+ int d3 = av_clip_uintp2((c0 - c3) >> 16, 12);
+
+ dest[0] = d0;
+ dest += line_size;
+ dest[0] = d1;
+ dest += line_size;
+ dest[0] = d2;
+ dest += line_size;
+ dest[0] = d3;
+}
+
+static void idct84_put_int16_12bit(uint16_t *dest, ptrdiff_t line_size, int16_t *block)
+{
+ line_size >>= 1;
+
+ for (int i = 0; i < 4; i++)
+ idctRowCondDC_int16_12bit(block + i * 8, 0);
+
+ for (int i = 0; i < 8; i++)
+ idct4ColPut_int16_12bit(dest + i, line_size, block + i);
+}
+
+static const int16_t dcval_tab[2][16] = {
+ { -1, -3, -7, -15,
+ -31, -63, -127, -255,
+ -511, -1023, -2047, -4095,
+ -8191, -16383, -32767, 0 },
+ { 1, 2, 4, 8,
+ 16, 32, 64, 128,
+ 256, 512, 1024, 2048,
+ 4096, 8192, 16384, 0 },
+};
+
+static const uint8_t dc_table[16][3] = {
+ { 0, 0, 15 }, { 0, 1, 0 }, { 1, 1, 1 }, { 2, 1, 2 },
+ { 3, 1, 3 }, { 4, 1, 4 }, { 5, 1, 5 }, { 6, 1, 6 },
+ { 7, 1, 7 }, { 8, 1, 8 }, { 9, 1, 9 }, { 10, 1, 10 },
+ { 11, 1, 11 }, { 12, 1, 12 }, { 13, 1, 13 }, { 14, 1, 14 },
+};
+
+static const uint8_t ac_table[194][2] = {
+ { 0, 1 }, { 0, 2 }, { 0, 3 }, { 0, 4 }, { 1, 1 }, { 255, 0 },
+ { 0, 5 }, { 1, 2 }, { 2, 1 }, { 3, 1 }, { 4, 1 }, { 0, 6 },
+ { 1, 3 }, { 5, 1 }, { 6, 1 }, { 0, 7 }, { 2, 2 }, { 7, 1 },
+ { 1, 4 }, { 3, 2 }, { 8, 1 }, { 9, 1 }, { 10, 1 }, { 0, 8 },
+ { 2, 3 }, { 4, 2 }, { 11, 1 }, { 12, 1 }, { 13, 1 }, { 15, 0 },
+ { 0, 12 },{ 0, 9 }, { 0, 10 }, { 0, 11 }, { 1, 5 }, { 6, 2 },
+ { 2, 4 }, { 3, 3 }, { 5, 2 }, { 7, 2 }, { 8, 2 }, { 1, 6 },
+ { 1, 7 }, { 1, 8 }, { 1, 9 }, { 1, 10 }, { 2, 5 }, { 2, 6 },
+ { 2, 7 }, { 2, 8 }, { 2, 9 }, { 2, 10 }, { 3, 4 }, { 3, 5 },
+ { 3, 6 }, { 3, 7 }, { 3, 8 }, { 3, 9 }, { 3, 10 }, { 4, 3 },
+ { 4, 4 }, { 4, 5 }, { 4, 6 }, { 4, 7 }, { 4, 8 }, { 4, 9 },
+ { 4, 10 }, { 5, 3 }, { 5, 4 }, { 5, 5 }, { 5, 6 }, { 5, 7 },
+ { 5, 8 }, { 5, 9 }, { 5, 10 }, { 6, 3 }, { 6, 4 }, { 6, 5 },
+ { 6, 6 }, { 6, 7 }, { 6, 8 }, { 6, 9 }, { 7, 3 }, { 7, 4 },
+ { 7, 5 }, { 7, 6 }, { 7, 7 }, { 7, 8 }, { 7, 9 }, { 8, 3 },
+ { 8, 4 }, { 8, 5 }, { 8, 6 }, { 8, 7 }, { 8, 8 }, { 8, 9 },
+ { 9, 2 }, { 9, 3 }, { 9, 4 }, { 9, 5 }, { 9, 6 }, { 9, 7 },
+ { 9, 8 }, { 9, 9 }, { 10, 2 }, { 10, 3 }, { 10, 4 }, { 10, 5 },
+ { 10, 6 }, { 10, 7 }, { 10, 8 }, { 10, 9 }, { 11, 2 }, { 11, 3 },
+ { 11, 4 }, { 11, 5 }, { 11, 6 }, { 11, 7 }, { 11, 8 }, { 11, 9 },
+ { 12, 2 }, { 12, 3 }, { 12, 4 }, { 12, 5 }, { 12, 6 }, { 12, 7 },
+ { 12, 8 }, { 12, 9 }, { 13, 2 }, { 13, 3 }, { 13, 4 }, { 13, 5 },
+ { 13, 6 }, { 13, 7 }, { 13, 8 }, { 13, 9 }, { 14, 1 }, { 14, 2 },
+ { 14, 3 }, { 14, 4 }, { 14, 5 }, { 14, 6 }, { 14, 7 }, { 14, 8 },
+ { 14, 9 }, { 15, 1 }, { 15, 2 }, { 15, 3 }, { 15, 4 }, { 15, 5 },
+ { 15, 6 }, { 15, 7 }, { 15, 8 }, { 15, 9 }, { 1, 11 }, { 1, 12 },
+ { 2, 11 }, { 2, 12 }, { 3, 11 }, { 3, 12 }, { 4, 11 }, { 4, 12 },
+ { 5, 11 }, { 5, 12 }, { 6, 10 }, { 6, 11 }, { 6, 12 }, { 7, 10 },
+ { 7, 11 }, { 7, 12 }, { 8, 10 }, { 8, 11 }, { 8, 12 }, { 9, 10 },
+ { 9, 11 }, { 9, 12 }, { 10, 10 }, { 10, 11 }, { 10, 12 }, { 11, 10 },
+ { 11, 11 }, { 11, 12 }, { 12, 10 }, { 12, 11 }, { 12, 12 }, { 13, 10 },
+ { 13, 11 }, { 13, 12 }, { 14, 10 }, { 14, 11 }, { 14, 12 }, { 15, 10 },
+ { 15, 11 }, { 15, 12 },
+};
+
+static int decode_block(AVCodecContext *avctx, GetBitContext *gbit,
+ int16_t *dst, const int *quant,
+ int *prev_dc, int max,
+ int mul, int add,
+ const uint8_t *scan)
+{
+ int dc_idx, sgnbit = 0, sign, len, val, code;
+
+ memset(dst, 0, 64 * 2);
+
+ dc_idx = get_vlc2(gbit, dc_vlc, DC_VLC_BITS, 2);
+ if (dc_idx < 0)
+ return AVERROR_INVALIDDATA;
+
+ sign = dc_table[dc_idx][1];
+ sgnbit = get_bitsz(gbit, sign);
+ len = dc_table[dc_idx][0];
+ code = get_bitsz(gbit, len);
+ val = code + *prev_dc + dcval_tab[sgnbit][dc_table[dc_idx][2]];
+ *prev_dc = val;
+ dst[0] = FFMIN(((val * quant[0] + 0x8000) >> 16) + add, 32767);
+
+ for (int i = 0;;) {
+ int skip, len, ac_idx;
+
+ ac_idx = get_vlc2(gbit, ac_vlc, AC_VLC_BITS, 3);
+ if (ac_idx < 0)
+ return AVERROR_INVALIDDATA;
+
+ skip = ac_table[ac_idx][0];
+ if (skip == 255)
+ break;
+
+ len = ac_table[ac_idx][1];
+ val = get_bits_long(gbit, len);
+ i = i + 1 + skip;
+ if (len && val < 1 << (len - 1))
+ val -= (1 << len) - 1;
+ dst[scan[i]] = (val * quant[scan[i]] + 0x8000) >> 16;
+ }
+
+ return 0;
+}
+
+static void decorrelate(AVCodecContext *avctx, uint8_t *data, ptrdiff_t linesize,
+ uint8_t *out0, uint8_t *out1, int pos_x, int pos_y)
+{
+ uint16_t *dst = (uint16_t *)(data + pos_y * linesize + pos_x * 2);
+ uint16_t *dst0 = (uint16_t *)(data + pos_y * linesize + pos_x * 2);
+ uint16_t *dst1 = (uint16_t *)(data + (pos_y + 1) * linesize + (pos_x + 1) * 2);
+ uint16_t *src0 = (uint16_t *)(out0);
+ uint16_t *src1 = (uint16_t *)(out1);
+
+ for (int y = 0; y < 4; y++) {
+ for (int x = 0; x < 8; x++) {
+ dst0[x*2] = av_clip_uintp2(dst0[x*2] + src1[x] - 2048, 12);
+ dst1[x*2] = av_clip_uintp2(dst1[x*2] + src0[x] - 2048, 12);
+ }
+
+ src0 += 8;
+ src1 += 8;
+ dst0 += linesize;
+ dst1 += linesize;
+ }
+
+ for (int y = 0; y < 8; y++) {
+ for (int x = 0; x < 16; x++)
+ dst[x] = (dst[x] << 4) + (dst[x] & 15);
+
+ dst += linesize >> 1;
+ }
+}
+
+static const uint8_t half_scan[] = {
+ 0, 1, 2, 3, 8, 9, 16, 17, 10, 11, 4, 5, 6, 7, 12, 13, 18,
+ 19, 24, 25, 26, 27, 20, 21, 14,15, 22, 23, 28, 29, 30, 31,
+};
+
+static int decode_tile_thread(AVCodecContext *avctx, void *arg, int jobnr, int threadnr)
+{
+ BRAWContext *s = avctx->priv_data;
+ BRAWTile *t = &s->tiles[jobnr];
+
+ GetBitContext gb;
+ int prev_dc[3];
+ int ret = 0;
+
+ LOCAL_ALIGNED_32(int16_t, block, [4], [64]);
+ LOCAL_ALIGNED_32(uint16_t, out, [2], [64]);
+
+ t->ret = -1;
+
+ ret = init_get_bits8(&gb, t->data, t->size);
+ if (ret < 0)
+ return ret;
+
+ prev_dc[0] = prev_dc[1] = prev_dc[2] = 0;
+
+ for (int y = 0; y < t->blocks_h_in_tile; y++) {
+ int pos_y = y * 8 + t->y * s->tile_size_h;
+
+ for (int x = 0; x < t->blocks_w_in_tile; x++) {
+ int pos_x = s->tile_offset_w[t->x] + x * 16;
+
+ ret = decode_block(avctx, &gb, block[0], s->quant[0], &prev_dc[0], 64, 1, 16384, ff_zigzag_direct);
+ if (ret < 0)
+ return ret;
+ ret = decode_block(avctx, &gb, block[1], s->quant[0], &prev_dc[0], 64, 1, 16384, ff_zigzag_direct);
+ if (ret < 0)
+ return ret;
+ ret = decode_block(avctx, &gb, block[2], s->quant[1], &prev_dc[1], 32, 1, 8192, half_scan);
+ if (ret < 0)
+ return ret;
+ ret = decode_block(avctx, &gb, block[3], s->quant[1], &prev_dc[2], 32, 1, 8192, half_scan);
+ if (ret < 0)
+ return ret;
+
+ ff_simple_idct_put_int16_12bit(s->frame->data[0] + pos_y * s->frame->linesize[0] + pos_x * 2,
+ s->frame->linesize[0], block[0]);
+ ff_simple_idct_put_int16_12bit(s->frame->data[0] + pos_y * s->frame->linesize[0] + pos_x * 2 + 16,
+ s->frame->linesize[0], block[1]);
+ idct84_put_int16_12bit(out[0], 16, block[2]);
+ idct84_put_int16_12bit(out[1], 16, block[3]);
+
+ decorrelate(avctx, s->frame->data[0], s->frame->linesize[0], (uint8_t *)out[0], (uint8_t *)out[1], pos_x, pos_y);
+
+ skip_bits(&gb, 8);
+ if (get_bits_left(&gb) < 0)
+ return AVERROR_INVALIDDATA;
+ }
+ }
+
+ t->ret = 0;
+ av_log(avctx, AV_LOG_DEBUG, "bits left: %d\n", get_bits_left(&gb));
+ return 0;
+}
+
+static int get_offset(AVCodecContext *avctx, int x)
+{
+ BRAWContext *s = avctx->priv_data;
+ GetByteContext *gb = &s->gb;
+ int a, b, nb, idx = 4;
+
+ a = bytestream2_get_byte(gb);
+ b = bytestream2_get_byte(gb);
+
+ nb = a * 2 + b;
+ if (nb != 0) {
+ int i = 0, j = 0;
+
+ while (i = j, (nb >> j & 1) == 0) {
+ j++;
+ }
+
+ idx = 4 - i;
+ }
+
+ s->offsets[x][0] = a << (idx & 0x1f);
+ s->offsets[x][1] = b << (idx & 0x1f);
+
+ av_log(avctx, AV_LOG_DEBUG, "offset:%d %dx%d\n", x, s->offsets[x][0], s->offsets[x][1]);
+
+ return 0;
+}
+
+static int get_offsets(AVCodecContext *avctx)
+{
+ for (int i = 0; i < 4; i++)
+ get_offset(avctx, i);
+
+ return 0;
+}
+
+static int decode_quants(AVCodecContext *avctx)
+{
+ BRAWContext *s = avctx->priv_data;
+ GetByteContext *gb = &s->gb;
+ int scale, dcq;
+
+ scale = (s->qscale[0] + 4) * 2048;
+ for (int n = 0; n < 64; n++)
+ s->quant[0][n] = bytestream2_get_be16(gb) * scale;
+
+ dcq = s->qscale[1];
+ if (s->quant[0][0] <= dcq)
+ s->quant[0][0] = dcq;
+
+ scale = lrint(fmax(4.0, round((s->qscale[0] + 4) * 0.5 + 0.5)) * 2048.);
+
+ for (int n = 0; n < 32; n++)
+ s->quant[1][n] = bytestream2_get_be16(gb) * scale;
+
+ dcq = s->qscale[2];
+ if (s->quant[1][0] <= dcq)
+ s->quant[1][0] = dcq;
+
+ return 0;
+}
+
+static int parse_frame_header(AVCodecContext *avctx)
+{
+ BRAWContext *s = avctx->priv_data;
+ GetByteContext *gb = &s->gb;
+
+ uint32_t braw_size;
+ int version, ret, w, h;
+ enum AVPixelFormat pix_fmt;
+
+ s->header_size = bytestream2_get_be32(gb);
+ if (s->header_size <= 8 ||
+ s->header_size - 8 >= bytestream2_get_bytes_left(gb))
+ return AVERROR_INVALIDDATA;
+ if (bytestream2_get_le32(gb) != MKTAG('b','m','d','f'))
+ return AVERROR_INVALIDDATA;
+ bytestream2_skip(gb, s->header_size - 8);
+
+ if (bytestream2_get_le32(gb) != MKTAG('b','r','a','w'))
+ return AVERROR_INVALIDDATA;
+ braw_size = bytestream2_get_be32(gb);
+ if (braw_size < 4352)
+ return AVERROR_INVALIDDATA;
+ if (braw_size - 8 > bytestream2_get_bytes_left(gb))
+ return AVERROR_INVALIDDATA;
+
+ version = bytestream2_get_byte(gb);
+ av_log(avctx, AV_LOG_DEBUG, "version: %d\n", version);
+ if (version != 1 && version != 2)
+ return AVERROR_INVALIDDATA;
+ s->qscale[0] = bytestream2_get_byte(gb);
+ av_log(avctx, AV_LOG_DEBUG, "qscale[0]: %d\n", s->qscale[0]);
+
+ s->nb_tiles_w = bytestream2_get_byte(gb);
+ s->nb_tiles_h = bytestream2_get_byte(gb);
+ av_log(avctx, AV_LOG_DEBUG, "nb_tiles: %dx%d\n", s->nb_tiles_w, s->nb_tiles_h);
+ if (!s->nb_tiles_w ||
+ !s->nb_tiles_h ||
+ s->nb_tiles_w * s->nb_tiles_h > BRAW_MAX_TILES)
+ return AVERROR_INVALIDDATA;
+
+ w = bytestream2_get_be16(gb);
+ h = bytestream2_get_be16(gb);
+ av_log(avctx, AV_LOG_DEBUG, "WxH: %dx%d\n", w, h);
+
+ s->tile_size_h = bytestream2_get_be16(gb);
+ av_log(avctx, AV_LOG_DEBUG, "tile_size_h = %d\n", s->tile_size_h);
+ if (s->tile_size_h & 7)
+ return AVERROR_INVALIDDATA;
+
+ bytestream2_skip(gb, 2);
+
+ ret = get_offsets(avctx);
+ if (ret < 0)
+ return ret;
+ bytestream2_skip(gb, 4);
+
+ s->qscale[1] = bytestream2_get_be16(gb);
+ av_log(avctx, AV_LOG_DEBUG, "qscale[1]: %d\n", s->qscale[1]);
+ s->qscale[2] = bytestream2_get_be16(gb);
+ av_log(avctx, AV_LOG_DEBUG, "qscale[2]: %d\n", s->qscale[2]);
+
+ bytestream2_skip(gb, 28);
+
+ s->tile_offset_w[0] = 0;
+
+ for (int x = 0; x < s->nb_tiles_w; x++) {
+ s->tile_size_w[x] = bytestream2_get_be16(gb);
+ s->tile_offset_w[x+1] = s->tile_offset_w[x] + s->tile_size_w[x];
+ av_log(avctx, AV_LOG_DEBUG, "tile_size_w[%d] = %d\n", x, s->tile_size_w[x]);
+ av_log(avctx, AV_LOG_DEBUG, "tile_offset_w[%d] = %d\n", x+1, s->tile_offset_w[x+1]);
+ if (s->tile_offset_w[x+1] > w)
+ return AVERROR_INVALIDDATA;
+ }
+
+ ret = ff_set_dimensions(avctx, s->tile_offset_w[s->nb_tiles_w], s->tile_size_h * s->nb_tiles_h);
+ if (ret < 0)
+ return ret;
+ avctx->width = w;
+ avctx->height = h;
+
+ pix_fmt = AV_PIX_FMT_BAYER_RGGB16;
+ avctx->bits_per_raw_sample = 12;
+ if (pix_fmt != s->pix_fmt) {
+ avctx->pix_fmt = s->pix_fmt = pix_fmt;
+ }
+
+ return 0;
+}
+
+static int parse_tiles(AVCodecContext *avctx)
+{
+ BRAWContext *s = avctx->priv_data;
+ GetByteContext *gb = &s->gb;
+
+ for (int x = 0; x < s->nb_tiles_w; x++) {
+ for (int y = 0; y < s->nb_tiles_h; y++) {
+ uint32_t offset;
+ BRAWTile *t = &s->tiles[y*s->nb_tiles_w + x];
+
+ int last_tile = (x == (s->nb_tiles_w - 1)) && (y == (s->nb_tiles_h - 1));
+
+ t->x = x;
+ t->y = y;
+ t->blocks_w_in_tile = s->tile_size_w[x] / 16;
+ if (y == s->nb_tiles_h - 1)
+ t->blocks_h_in_tile = (avctx->height - y * s->tile_size_h) / 8;
+ else
+ t->blocks_h_in_tile = s->tile_size_h / 8;
+ offset = bytestream2_get_be32(gb);
+ t->size = last_tile ? bytestream2_size(gb) - offset - s->header_size : bytestream2_peek_be32(gb) - offset;
+
+ if (offset > bytestream2_size(gb) || t->size <= 0)
+ return AVERROR_INVALIDDATA;
+
+ t->data = gb->buffer_start + offset + s->header_size;
+
+ av_log(avctx, AV_LOG_DEBUG, "%dx%d: tile_bitstream_size: 0x%X, tile_bitstream_offset: 0x%X\n", x, y, t->size, offset + s->header_size);
+ }
+ }
+
+ return 0;
+}
+
+static int decode_frame(AVCodecContext *avctx)
+{
+ BRAWContext *s = avctx->priv_data;
+ int error = 0, tile_count = s->nb_tiles_w * s->nb_tiles_h;
+
+ avctx->execute2(avctx, decode_tile_thread, NULL, NULL, tile_count);
+
+ for (int i = 0; i < tile_count; i++)
+ error += s->tiles[i].ret < 0;
+
+ if (error)
+ s->frame->decode_error_flags = FF_DECODE_ERROR_INVALID_BITSTREAM;
+ if (error < tile_count)
+ return 0;
+
+ return s->tiles[0].ret;
+}
+
+static int braw_decode_frame(AVCodecContext *avctx, AVFrame *f, int *got_frame,
+ AVPacket *avpkt)
+{
+ int ret;
+ BRAWContext *s = avctx->priv_data;
+
+ if (avpkt->size <= 4608)
+ return AVERROR_INVALIDDATA;
+
+ bytestream2_init(&s->gb, avpkt->data, avpkt->size);
+ ret = parse_frame_header(avctx);
+ if (ret < 0)
+ return ret;
+
+ ret = ff_thread_get_buffer(avctx, f, 0);
+ if (ret < 0)
+ return ret;
+ ff_thread_finish_setup(avctx);
+
+ bytestream2_seek(&s->gb, 0x1180, SEEK_SET);
+ ret = decode_quants(avctx);
+ if (ret < 0)
+ return ret;
+
+ bytestream2_seek(&s->gb, 0x180, SEEK_SET);
+ ret = parse_tiles(avctx);
+ if (ret < 0)
+ return ret;
+
+ s->frame = f;
+ ret = decode_frame(avctx);
+ if (ret < 0)
+ return ret;
+
+ f->pict_type = AV_PICTURE_TYPE_I;
+ f->flags = AV_FRAME_FLAG_KEY;
+ *got_frame = 1;
+
+ return avpkt->size;
+}
+
+static av_cold int braw_decode_init(AVCodecContext *avctx)
+{
+ BRAWContext *s = avctx->priv_data;
+ static AVOnce init_once = AV_ONCE_INIT;
+ int ret;
+
+ ff_idctdsp_init(&s->idsp, avctx);
+ ff_init_scantable(s->idsp.idct_permutation, &s->scan, ff_zigzag_direct);
+
+ ret = ff_thread_once(&init_once, braw_static_init);
+ if (ret)
+ return AVERROR_UNKNOWN;
+
+ s->pix_fmt = AV_PIX_FMT_NONE;
+
+ return 0;
+}
+
+#if HAVE_THREADS
+static int update_thread_context(AVCodecContext *dst, const AVCodecContext *src)
+{
+ BRAWContext *csrc = src->priv_data;
+ BRAWContext *cdst = dst->priv_data;
+
+ cdst->pix_fmt = csrc->pix_fmt;
+
+ return 0;
+}
+#endif
+
+const FFCodec ff_braw_decoder = {
+ .p.name = "braw",
+ CODEC_LONG_NAME("Blackmagic RAW"),
+ .p.type = AVMEDIA_TYPE_VIDEO,
+ .p.id = AV_CODEC_ID_BRAW,
+ .priv_data_size = sizeof(BRAWContext),
+ .init = braw_decode_init,
+ FF_CODEC_DECODE_CB(braw_decode_frame),
+ UPDATE_THREAD_CONTEXT(update_thread_context),
+ .p.capabilities = AV_CODEC_CAP_DR1 |
+ AV_CODEC_CAP_SLICE_THREADS |
+ AV_CODEC_CAP_FRAME_THREADS,
+ .caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
+};
+
--
2.49.0.395.g12beb8f557c
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [FFmpeg-devel] [PATCH 3/3] avcodec: add Blackmagic RAW decoder
2025-04-15 10:04 ` [FFmpeg-devel] [PATCH 3/3] avcodec: add Blackmagic RAW decoder Lynne
@ 2025-04-15 12:07 ` Lynne
0 siblings, 0 replies; 4+ messages in thread
From: Lynne @ 2025-04-15 12:07 UTC (permalink / raw)
To: FFmpeg development discussions and patches
On 15/04/2025 12:04, Lynne wrote:
> Most of the work was done by Paul B Mahol.
> I cleaned the patch up, improved the code a bit, and added slice
> threading.
> ---
> configure | 1 +
> libavcodec/Makefile | 1 +
> libavcodec/allcodecs.c | 1 +
> libavcodec/braw.c | 666 +++++++++++++++++++++++++++++++++++++++++
> 4 files changed, 669 insertions(+)
> create mode 100755 libavcodec/braw.c
Output is kinda-bayer but apparently not.
Patch dropped.
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2025-04-15 12:07 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-04-15 10:04 [FFmpeg-devel] [PATCH 1/3] avcodec: add AV_CODEC_ID_BRAW Lynne
2025-04-15 10:04 ` [FFmpeg-devel] [PATCH 2/3] lavf/mov: support demuxing Blackmagic RAW streams Lynne
2025-04-15 10:04 ` [FFmpeg-devel] [PATCH 3/3] avcodec: add Blackmagic RAW decoder Lynne
2025-04-15 12:07 ` Lynne
Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
This inbox may be cloned and mirrored by anyone:
git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git
# If you have public-inbox 1.1+ installed, you may
# initialize and index your mirror using the following commands:
public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \
ffmpegdev@gitmailbox.com
public-inbox-index ffmpegdev
Example config snippet for mirrors.
AGPL code for this site: git clone https://public-inbox.org/public-inbox.git