[FFmpeg-devel] [PATCH 2/2] fix _Float16 use and lots of LSB alignment flaws
Martin Schitter
ms+git at mur.at
Mon Aug 26 22:07:34 EEST 2024
---
libavcodec/dnxucdec.c | 179 ++++++++++++++++++++++++------------------
1 file changed, 102 insertions(+), 77 deletions(-)
diff --git a/libavcodec/dnxucdec.c b/libavcodec/dnxucdec.c
index de9e06f..74369db 100644
--- a/libavcodec/dnxucdec.c
+++ b/libavcodec/dnxucdec.c
@@ -29,7 +29,7 @@
shortcomings are affecting the range of available formats (no YUV half and
float pixel formats and filters are provided by ffmpeg until now and RGB half
content always requires an alpha plane).
-
+
A wide range of DNxUncompressed formats are nevertheless already supported:
- YUV 4:2:2 8-/10-/12-bit
@@ -37,14 +37,12 @@
*/
-
#include "avcodec.h"
#include "codec_internal.h"
#include "decode.h"
#include "libavutil/imgutils.h"
#include "thread.h"
-
typedef struct DNxUcParseContext {
uint32_t fourcc_tag;
uint32_t width;
@@ -52,7 +50,7 @@ typedef struct DNxUcParseContext {
uint32_t nr_bytes;
} DNxUcParseContext;
-/*
+/*
DNxUncompressed frame data comes wrapped in simple metadata
and fourcc markers:
@@ -61,13 +59,13 @@ and fourcc markers:
[8-11] unknown value (allways: 0x15)
[12-15] fourcc 'sinf'
[16-19] frame width / line packing size
-[20-23] frame hight / nr of lines
+[20-23] frame hig5c1c0325cd1bd3f826bbd73dffd0b07974a586bdht / nr of lines
[24-27] fourcc pixel format indicator
[28] unknown value (alpha?)
[29-32] nr of bytes in frame data + 8
[33-36] fourcc 'sdat'
[37-..] frame data
- */
+*/
static int dnxuc_parse(AVCodecParserContext *s,
AVCodecContext *avctx,
@@ -98,10 +96,10 @@ static int dnxuc_parse(AVCodecParserContext *s,
if (!avctx->codec_tag) {
av_fourcc_make_string(fourcc_buf, pc->fourcc_tag);
- av_log(0, AV_LOG_INFO, "dnxuc_parser: '%s' %dx%d %dbpp %d\n",
- fourcc_buf,
- pc->width, pc->height,
- (pc->nr_bytes*8)/(pc->width*pc->height),
+ av_log(0, AV_LOG_INFO, "dnxuc_parser: '%s' %dx%d %dbpp %d\n",
+ fourcc_buf,
+ pc->width, pc->height,
+ (pc->nr_bytes*8)/(pc->width*pc->height),
pc->nr_bytes);
avctx->codec_tag = pc->fourcc_tag;
}
@@ -149,7 +147,7 @@ static int float2planes(AVCodecContext *avctx, AVFrame *frame, const AVPacket *p
lw = frame->width;
- for(y = 0; y < frame->height; y++){
+ for(y = 0; y < frame->height; y++){
for(x = 0; x < frame->width; x++){
memcpy(&frame->data[2][sof*(lw*y + x)], &pkt->data[sof* 3*(lw*y + x)], sof);
memcpy(&frame->data[0][sof*(lw*y + x)], &pkt->data[sof*(3*(lw*y + x) + 1)], sof);
@@ -166,7 +164,7 @@ static int half_add_alpha(AVCodecContext *avctx, AVFrame *frame, const AVPacket
int ret, x, y, lw;
const size_t soh = 2;
- const _Float16 opaque = 1.0;
+ const uint16_t opaque = 0x3c00;
ret = ff_thread_get_buffer(avctx, frame, 0);
if (ret < 0)
@@ -174,7 +172,7 @@ static int half_add_alpha(AVCodecContext *avctx, AVFrame *frame, const AVPacket
lw = frame->width;
- for(y = 0; y < frame->height; y++){
+ for(y = 0; y < frame->height; y++){
for(x = 0; x < frame->width; x++){
memcpy(&frame->data[0][soh*4*(lw*y + x)], &pkt->data[soh*3*(lw*y + x)], soh*3);
memcpy(&frame->data[0][soh*(4*(lw*y + x) + 3)], &opaque, soh);
@@ -185,8 +183,8 @@ static int half_add_alpha(AVCodecContext *avctx, AVFrame *frame, const AVPacket
/* DNxUncompressed utilizes a very dense bitpack representation of 10bit and 12bit pixel data.
-Lines of Image data, which look like in their ordinary 8bit counterpart, contain the most
-significant upper bits of the pixel data. These sections alternate with shorter segments in
+Lines of Image data, which look like in their ordinary 8bit counterpart, contain the most
+significant upper bits of the pixel data. These sections alternate with shorter segments in
which the complementary least significant bits of information get packed in a gapless sequence.
+----------------------+ +----------------------+ +------------------------+ +----------~
@@ -203,11 +201,11 @@ next line of MSB bytes... */
static int unpack_rg10(AVCodecContext *avctx, AVFrame *frame, const AVPacket *pkt){
- int ret, x, y, lw, msp, pack, lsp;
+ int ret, x, y, lw, msp, pack, lsp, p_off;
uint16_t r,g,b;
if (avctx->width % 4){
- av_log(0, AV_LOG_ERROR,
+ av_log(0, AV_LOG_ERROR,
"Image width has to be dividable by 4 for 10bit RGB DNxUncompressed!\n");
return AVERROR_EXIT;
}
@@ -218,22 +216,31 @@ static int unpack_rg10(AVCodecContext *avctx, AVFrame *frame, const AVPacket *pk
lw = frame->width;
- for(y = 0; y < frame->height; y++){
+ for(y = 0; y < frame->height; y++){
for(x = 0; x < frame->width; x++){
msp = pkt->data[y*3*(lw + lw/4) + 3*x];
- pack = pkt->data[y*(3*(lw + lw/4)) + 3*lw + 3*x/4];
- lsp = (pack >> (x%4)*2) & 0x3;
+ p_off = y*(3*(lw + lw/4)) + 3*lw + 3*x/4;
+ pack = pkt->data[p_off];
+ lsp = (pack >> (3*x%4)*2) & 0x3;
r = (msp << 2) + lsp;
+ // av_log(0, AV_LOG_DEBUG, "r: %04x, %02x, %02x, %02x, %d\n",
+ // r, msp, lsp, pack, p_off);
msp = pkt->data[y*3*(lw + lw/4) + 3*x + 1];
- pack = pkt->data[y*(3*(lw + lw/4)) + 3*lw + 3*(x+1)/4];
- lsp = (pack >> ((x+1)%4)*2) & 0x3;
- g = (msp << 2) + lsp;
-
+ p_off = y*(3*(lw + lw/4)) + 3*lw + (3*x+1)/4;
+ pack = pkt->data[p_off];
+ lsp = (pack >> ((3*x+1)%4)*2) & 0x3;
+ g = (msp << 2) + lsp;
+ // av_log(0, AV_LOG_DEBUG, "g: %04x, %02x, %02x, %02x, %d\n",
+ // g, msp, lsp, pack, p_off);
+
msp = pkt->data[y*3*(lw + lw/4) + 3*x + 2];
- pack = pkt->data[y*(3*(lw + lw/4)) + 3*lw + 3*(x+2)/4];
- lsp = (pack >> ((x+2)%4)*2) & 0x3;
+ p_off = y*(3*(lw + lw/4)) + 3*lw + (3*x+2)/4;
+ pack = pkt->data[p_off];
+ lsp = (pack >> ((3*x+2)%4)*2) & 0x3;
b = (msp << 2) + lsp;
+ // av_log(0, AV_LOG_DEBUG, "b: %04x, %02x, %02x, %02x, %d\n\n",
+ // b, msp, lsp, pack, p_off);
memcpy(&frame->data[2][2*(y*lw + x)], &r, 2);
memcpy(&frame->data[0][2*(y*lw + x)], &g, 2);
@@ -245,11 +252,11 @@ static int unpack_rg10(AVCodecContext *avctx, AVFrame *frame, const AVPacket *pk
static int unpack_rg12(AVCodecContext *avctx, AVFrame *frame, const AVPacket *pkt){
- int ret, x, y, lw, msp, pack, lsp;
+ int ret, x, y, lw, msp, pack, lsp, p_off;
uint16_t r,g,b;
if (avctx->width % 2){
- av_log(0, AV_LOG_ERROR,
+ av_log(0, AV_LOG_ERROR,
"Image width has to be dividable by 2 for 12bit RGB DNxUncompressed!\n");
return AVERROR_EXIT;
}
@@ -260,22 +267,31 @@ static int unpack_rg12(AVCodecContext *avctx, AVFrame *frame, const AVPacket *pk
lw = frame->width;
- for(y = 0; y < frame->height; y++){
+ for(y = 0; y < frame->height; y++){
for(x = 0; x < frame->width; x++){
msp = pkt->data[y*3*(lw + lw/2) + 3*x];
- pack = pkt->data[y*(3*(lw + lw/2)) + 3*lw + 3*x/2];
- lsp = (pack >> (x%2)*4) & 0xf;
+ p_off = y*(3*(lw + lw/2)) + 3*lw + 3*x/2;
+ pack = pkt->data[p_off];
+ lsp = (pack >> (3*x%2)*4) & 0xf;
r = (msp << 4) + lsp;
+ // av_log(0, AV_LOG_DEBUG, "r: %04x, %02x, %02x, %02x, %d\n",
+ // r, msp, lsp, pack, p_off);
msp = pkt->data[y*3*(lw + lw/2) + 3*x + 1];
- pack = pkt->data[y*(3*(lw + lw/2)) + 3*lw + 3*(x+1)/2];
- lsp = (pack >> ((x+1)%2)*4) & 0xf;
- g = (msp << 4) + lsp;
-
+ p_off =y*(3*(lw + lw/2)) + 3*lw + (3*x+1)/2;
+ pack = pkt->data[p_off];
+ lsp = (pack >> ((3*x+1)%2)*4) & 0xf;
+ g = (msp << 4) + lsp;
+ // av_log(0, AV_LOG_DEBUG, "g: %04x, %02x, %02x, %02x, %d\n",
+ // g, msp, lsp, pack, p_off);
+
msp = pkt->data[y*3*(lw + lw/2) + 3*x + 2];
- pack = pkt->data[y*(3*(lw + lw/2)) + 3*lw + 3*(x+2)/2];
- lsp = (pack >> ((x+2)%2)*4) & 0xf;
+ p_off = y*(3*(lw + lw/2)) + 3*lw + (3*x+2)/2;
+ pack = pkt->data[p_off];
+ lsp = (pack >> ((3*x+2)%2)*4) & 0xf;
b = (msp << 4) + lsp;
+ // av_log(0, AV_LOG_DEBUG, "b: %04x, %02x, %02x, %02x, %d\n\n",
+ // b, msp, lsp, pack, p_off);
memcpy(&frame->data[2][2*(y*lw + x)], &r, 2);
memcpy(&frame->data[0][2*(y*lw + x)], &g, 2);
@@ -288,11 +304,11 @@ static int unpack_rg12(AVCodecContext *avctx, AVFrame *frame, const AVPacket *pk
static int unpack_y210(AVCodecContext *avctx, AVFrame *frame, const AVPacket *pkt){
- int ret, x, y, lw, msp, pack, lsp;
+ int ret, x, y, lw, msp, pack, lsp, p_off;
uint16_t y1, y2, u, v;
if (avctx->width % 2){
- av_log(0, AV_LOG_ERROR,
+ av_log(0, AV_LOG_ERROR,
"Image width has to be dividable by 2 for 10bit YUV 4:2:2 DNxUncompressed!\n");
return AVERROR_EXIT;
}
@@ -303,27 +319,35 @@ static int unpack_y210(AVCodecContext *avctx, AVFrame *frame, const AVPacket *pk
lw = frame->width;
- for(y = 0; y < frame->height; y++){
+ for(y = 0; y < frame->height; y++){
for(x = 0; x < frame->width; x += 2){
+
+ p_off = y*(2*(lw + lw/4)) + 2*lw + x/2;
+ pack = pkt->data[p_off];
+
msp = pkt->data[y*2*(lw + lw/4) + 2*x];
- pack = pkt->data[y*(2*(lw + lw/4)) + 2*lw + 2*x/4];
- lsp = (pack >> (x%4)*2) & 0x3;
+ lsp = pack & 0x3;
u = (msp << 2) + lsp;
+ // av_log(0, AV_LOG_DEBUG, " u: %04x, %02x, %02x, %02x, %d\n",
+ // u, msp, lsp, pack, p_off);
msp = pkt->data[y*2*(lw + lw/4) + 2*x + 1];
- pack = pkt->data[y*(2*(lw + lw/4)) + 2*lw + 2*x/4];
- lsp = (pack >> ((x+1)%4)*2) & 0x3;
- y1 = (msp << 2) + lsp;
-
+ lsp = (pack >> 2) & 0x3;
+ y1 = (msp << 2) + lsp;
+ // av_log(0, AV_LOG_DEBUG, "y1: %04x, %02x, %02x, %02x, %d\n",
+ // y1, msp, lsp, pack, p_off);
+
msp = pkt->data[y*2*(lw + lw/4) + 2*x + 2];
- pack = pkt->data[y*(2*(lw + lw/4)) + 2*lw + 2*x/4];
- lsp = (pack >> ((x+2)%4)*2) & 0x3;
+ lsp = (pack >> 4) & 0x3;
v = (msp << 2) + lsp;
+ // av_log(0, AV_LOG_DEBUG, " v: %04x, %02x, %02x, %02x, %d\n",
+ // v, msp, lsp, pack, p_off);
msp = pkt->data[y*2*(lw + lw/4) + 2*x + 3];
- pack = pkt->data[y*(2*(lw + lw/4)) + 2*lw + 2*(x+2)/4];
- lsp = (pack >> ((x+3)%4)*2) & 0x3;
+ lsp = (pack >> 6) & 0x3;
y2 = (msp << 2) + lsp;
+ // av_log(0, AV_LOG_DEBUG, "y2: %04x, %02x, %02x, %02x, %d\n\n",
+ // y2, msp, lsp, pack, p_off);
memcpy(&frame->data[0][2*(y*lw + x)], &y1, 2);
memcpy(&frame->data[0][2*(y*lw + x+1)], &y2, 2);
@@ -337,11 +361,11 @@ static int unpack_y210(AVCodecContext *avctx, AVFrame *frame, const AVPacket *pk
static int unpack_y212(AVCodecContext *avctx, AVFrame *frame, const AVPacket *pkt){
- int ret, x, y, lw, msp, pack, lsp;
+ int ret, x, y, lw, msp, pack, lsp, p_off;
uint16_t y1, y2, u, v;
if (avctx->width % 2){
- av_log(0, AV_LOG_ERROR,
+ av_log(0, AV_LOG_ERROR,
"Image width has to be dividable by 2 for 12bit YUV 4:2:2 DNxUncompressed!\n");
return AVERROR_EXIT;
}
@@ -352,27 +376,38 @@ static int unpack_y212(AVCodecContext *avctx, AVFrame *frame, const AVPacket *pk
lw = frame->width;
- for(y = 0; y < frame->height; y++){
+ for(y = 0; y < frame->height; y++){
for(x = 0; x < frame->width; x += 2){
+
+ p_off = y*(2*(lw + lw/2)) + 2*lw + x;
+ pack = pkt->data[p_off];
+
msp = pkt->data[y*2*(lw + lw/2) + 2*x];
- pack = pkt->data[y*(2*(lw + lw/2)) + 2*lw + 2*x/2];
- lsp = (pack >> (x%2)*4) & 0xf;
+ lsp = pack & 0xf;
u = (msp << 4) + lsp;
+ // av_log(0, AV_LOG_DEBUG, " u: %04x, %02x, %02x, %02x, %d\n",
+ // u, msp, lsp, pack, p_off);
msp = pkt->data[y*2*(lw + lw/2) + 2*x + 1];
- pack = pkt->data[y*(2*(lw + lw/2)) + 2*lw + 2*x/2];
- lsp = (pack >> ((x+1)%2)*4) & 0xf;
- y1 = (msp << 4) + lsp;
-
+ lsp = (pack >> 4) & 0xf;
+ y1 = (msp << 4) + lsp;
+ // av_log(0, AV_LOG_DEBUG, "y1: %04x, %02x, %02x, %02x, %d\n",
+ // y1, msp, lsp, pack, p_off);
+
+ p_off = y*(2*(lw + lw/2)) + 2*lw + x+1;
+ pack = pkt->data[p_off];
+
msp = pkt->data[y*2*(lw + lw/2) + 2*x + 2];
- pack = pkt->data[y*(2*(lw + lw/2)) + 2*lw + 2*x/2];
- lsp = (pack >> ((x+2)%2)*4) & 0xf;
+ lsp = pack & 0xf;
v = (msp << 4) + lsp;
+ // av_log(0, AV_LOG_DEBUG, " v: %04x, %02x, %02x, %02x, %d\n",
+ // v, msp, lsp, pack, p_off);
msp = pkt->data[y*2*(lw + lw/2) + 2*x + 3];
- pack = pkt->data[y*(2*(lw + lw/2)) + 2*lw + 2*(x+2)/2];
- lsp = (pack >> ((x+3)%3)*4) & 0xf;
+ lsp = (pack >> 4) & 0xf;
y2 = (msp << 4) + lsp;
+ // av_log(0, AV_LOG_DEBUG, "y2: %04x, %02x, %02x, %02x, %d\n\n",
+ // y2, msp, lsp, pack, p_off);
memcpy(&frame->data[0][2*(y*lw + x)], &y1, 2);
memcpy(&frame->data[0][2*(y*lw + x+1)], &y2, 2);
@@ -388,8 +423,8 @@ static int dnxuc_decode_frame(AVCodecContext *avctx, AVFrame *frame,
int *got_frame, AVPacket *avpkt) {
char fourcc_buf[5];
- int i, ret;
-
+ int ret;
+
switch (avctx->codec_tag) {
case MKTAG('r','g','0','8'):
avctx->pix_fmt = AV_PIX_FMT_RGB24;
@@ -427,8 +462,8 @@ static int dnxuc_decode_frame(AVCodecContext *avctx, AVFrame *frame,
default:
av_fourcc_make_string(fourcc_buf, avctx->codec_tag);
- av_log(0, AV_LOG_ERROR,
- "Unsupported DNxUncompressed pixel format variant: '%s'\n",
+ av_log(0, AV_LOG_ERROR,
+ "Unsupported DNxUncompressed pixel format variant: '%s'\n",
fourcc_buf);
return AVERROR(ENOSYS);
}
@@ -438,14 +473,6 @@ static int dnxuc_decode_frame(AVCodecContext *avctx, AVFrame *frame,
return ret;
}
- for (i = 0; frame->data[i]; i++){
- av_log(0, AV_LOG_DEBUG,
- "frame(%ld) data[%d] dump: %02x %02x %02x %02x %02x %02x %02x %02x ...\n",
- avctx->frame_num, i,
- frame->data[i][0], frame->data[i][1], frame->data[i][2], frame->data[i][3],
- frame->data[i][4], frame->data[i][5], frame->data[i][6], frame->data[i][7]);
- }
-
*got_frame = 1;
return avpkt->size;
@@ -454,9 +481,7 @@ static int dnxuc_decode_frame(AVCodecContext *avctx, AVFrame *frame,
const AVCodecParser ff_dnxuc_parser = {
.codec_ids = { AV_CODEC_ID_DNXUC },
.priv_data_size = sizeof(DNxUcParseContext),
- //.parser_init = dnxuc_parser_init,
.parser_parse = dnxuc_parse,
- //.parser_close = dnxuc_parser_close,
};
const FFCodec ff_dnxuc_decoder = {
--
2.45.2
More information about the ffmpeg-devel
mailing list