]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/proresdec2.c
avcodec/v4l2_m2m: Cosmetics
[ffmpeg] / libavcodec / proresdec2.c
index 94323df1282ed4822b86413b90fe091a7438f56d..2652a31c81f9c7e90457d4e0ee2f0bebddc920f7 100644 (file)
@@ -46,9 +46,13 @@ static void permute(uint8_t *dst, const uint8_t *src, const uint8_t permutation[
         dst[i] = permutation[src[i]];
 }
 
-static void unpack_alpha_10(GetBitContext *gb, uint16_t *dst, int num_coeffs,
-                            const int num_bits)
-{
+#define ALPHA_SHIFT_16_TO_10(alpha_val) (alpha_val >> 6)
+#define ALPHA_SHIFT_8_TO_10(alpha_val)  ((alpha_val << 2) | (alpha_val >> 6))
+#define ALPHA_SHIFT_16_TO_12(alpha_val) (alpha_val >> 4)
+#define ALPHA_SHIFT_8_TO_12(alpha_val)  ((alpha_val << 4) | (alpha_val >> 4))
+
+static void inline unpack_alpha(GetBitContext *gb, uint16_t *dst, int num_coeffs,
+                                const int num_bits, const int decode_precision) {
     const int mask = (1 << num_bits) - 1;
     int i, idx, val, alpha_val;
 
@@ -68,9 +72,17 @@ static void unpack_alpha_10(GetBitContext *gb, uint16_t *dst, int num_coeffs,
             }
             alpha_val = (alpha_val + val) & mask;
             if (num_bits == 16) {
-                dst[idx++] = alpha_val >> 6;
+                if (decode_precision == 10) {
+                    dst[idx++] = ALPHA_SHIFT_16_TO_10(alpha_val);
+                } else { /* 12b */
+                    dst[idx++] = ALPHA_SHIFT_16_TO_12(alpha_val);
+                }
             } else {
-                dst[idx++] = (alpha_val << 2) | (alpha_val >> 6);
+                if (decode_precision == 10) {
+                    dst[idx++] = ALPHA_SHIFT_8_TO_10(alpha_val);
+                } else { /* 12b */
+                    dst[idx++] = ALPHA_SHIFT_8_TO_12(alpha_val);
+                }
             }
             if (idx >= num_coeffs)
                 break;
@@ -81,16 +93,45 @@ static void unpack_alpha_10(GetBitContext *gb, uint16_t *dst, int num_coeffs,
         if (idx + val > num_coeffs)
             val = num_coeffs - idx;
         if (num_bits == 16) {
-            for (i = 0; i < val; i++)
-                dst[idx++] = alpha_val >> 6;
+            for (i = 0; i < val; i++) {
+                if (decode_precision == 10) {
+                    dst[idx++] = ALPHA_SHIFT_16_TO_10(alpha_val);
+                } else { /* 12b */
+                    dst[idx++] = ALPHA_SHIFT_16_TO_12(alpha_val);
+                }
+            }
         } else {
-            for (i = 0; i < val; i++)
-                dst[idx++] = (alpha_val << 2) | (alpha_val >> 6);
-
+            for (i = 0; i < val; i++) {
+                if (decode_precision == 10) {
+                    dst[idx++] = ALPHA_SHIFT_8_TO_10(alpha_val);
+                } else { /* 12b */
+                    dst[idx++] = ALPHA_SHIFT_8_TO_12(alpha_val);
+                }
+            }
         }
     } while (idx < num_coeffs);
 }
 
+static void unpack_alpha_10(GetBitContext *gb, uint16_t *dst, int num_coeffs,
+                            const int num_bits)
+{
+    if (num_bits == 16) {
+        unpack_alpha(gb, dst, num_coeffs, 16, 10);
+    } else { /* 8 bits alpha */
+        unpack_alpha(gb, dst, num_coeffs, 8, 10);
+    }
+}
+
+static void unpack_alpha_12(GetBitContext *gb, uint16_t *dst, int num_coeffs,
+                            const int num_bits)
+{
+    if (num_bits == 16) {
+        unpack_alpha(gb, dst, num_coeffs, 16, 12);
+    } else { /* 8 bits alpha */
+        unpack_alpha(gb, dst, num_coeffs, 8, 12);
+    }
+}
+
 static av_cold int decode_init(AVCodecContext *avctx)
 {
     int ret = 0;
@@ -114,15 +155,23 @@ static av_cold int decode_init(AVCodecContext *avctx)
         break;
     case MKTAG('a','p','4','h'):
         avctx->profile = FF_PROFILE_PRORES_4444;
+        avctx->bits_per_raw_sample = 12;
         break;
     case MKTAG('a','p','4','x'):
         avctx->profile = FF_PROFILE_PRORES_XQ;
+        avctx->bits_per_raw_sample = 12;
         break;
     default:
         avctx->profile = FF_PROFILE_UNKNOWN;
         av_log(avctx, AV_LOG_WARNING, "Unknown prores profile %d\n", avctx->codec_tag);
     }
 
+    if (avctx->bits_per_raw_sample == 10) {
+        av_log(avctx, AV_LOG_DEBUG, "Auto bitdepth precision. Use 10b decoding based on codec tag.\n");
+    } else { /* 12b */
+        av_log(avctx, AV_LOG_DEBUG, "Auto bitdepth precision. Use 12b decoding based on codec tag.\n");
+    }
+
     ff_blockdsp_init(&ctx->bdsp, avctx);
     ret = ff_proresdsp_init(&ctx->prodsp, avctx);
     if (ret < 0) {
@@ -138,6 +187,8 @@ static av_cold int decode_init(AVCodecContext *avctx)
 
     if (avctx->bits_per_raw_sample == 10){
         ctx->unpack_alpha = unpack_alpha_10;
+    } else if (avctx->bits_per_raw_sample == 12){
+        ctx->unpack_alpha = unpack_alpha_12;
     } else {
         av_log(avctx, AV_LOG_ERROR, "Fail to set unpack_alpha for bits per raw sample %d\n", avctx->bits_per_raw_sample);
         return AVERROR_BUG;
@@ -168,10 +219,14 @@ static int decode_frame_header(ProresContext *ctx, const uint8_t *buf,
 
     width  = AV_RB16(buf + 8);
     height = AV_RB16(buf + 10);
+
     if (width != avctx->width || height != avctx->height) {
-        av_log(avctx, AV_LOG_ERROR, "picture resolution change: %dx%d -> %dx%d\n",
+        int ret;
+
+        av_log(avctx, AV_LOG_WARNING, "picture resolution change: %dx%d -> %dx%d\n",
                avctx->width, avctx->height, width, height);
-        return AVERROR_PATCHWELCOME;
+        if ((ret = ff_set_dimensions(avctx, width, height)) < 0)
+            return ret;
     }
 
     ctx->frame_type = (buf[12] >> 2) & 3;
@@ -194,9 +249,17 @@ static int decode_frame_header(ProresContext *ctx, const uint8_t *buf,
     }
 
     if (ctx->alpha_info) {
-        avctx->pix_fmt = (buf[12] & 0xC0) == 0xC0 ? AV_PIX_FMT_YUVA444P10 : AV_PIX_FMT_YUVA422P10;
+        if (avctx->bits_per_raw_sample == 10) {
+            avctx->pix_fmt = (buf[12] & 0xC0) == 0xC0 ? AV_PIX_FMT_YUVA444P10 : AV_PIX_FMT_YUVA422P10;
+        } else { /* 12b */
+            avctx->pix_fmt = (buf[12] & 0xC0) == 0xC0 ? AV_PIX_FMT_YUVA444P12 : AV_PIX_FMT_YUVA422P12;
+        }
     } else {
-        avctx->pix_fmt = (buf[12] & 0xC0) == 0xC0 ? AV_PIX_FMT_YUV444P10 : AV_PIX_FMT_YUV422P10;
+        if (avctx->bits_per_raw_sample == 10) {
+            avctx->pix_fmt = (buf[12] & 0xC0) == 0xC0 ? AV_PIX_FMT_YUV444P10 : AV_PIX_FMT_YUV422P10;
+        } else { /* 12b */
+            avctx->pix_fmt = (buf[12] & 0xC0) == 0xC0 ? AV_PIX_FMT_YUV444P12 : AV_PIX_FMT_YUV422P12;
+        }
     }
 
     avctx->color_primaries = buf[14];
@@ -542,6 +605,7 @@ static void decode_slice_alpha(ProresContext *ctx,
     }
 
     block = blocks;
+
     for (i = 0; i < 16; i++) {
         memcpy(dst, block, 16 * blocks_per_slice * sizeof(*dst));
         dst   += dst_stride >> 1;
@@ -563,6 +627,7 @@ static int decode_slice_thread(AVCodecContext *avctx, void *arg, int jobnr, int
     LOCAL_ALIGNED_16(int16_t, qmat_chroma_scaled,[64]);
     int mb_x_shift;
     int ret;
+    uint16_t val_no_chroma;
 
     slice->ret = -1;
     //av_log(avctx, AV_LOG_INFO, "slice %d mb width %d mb x %d y %d\n",
@@ -600,7 +665,8 @@ static int decode_slice_thread(AVCodecContext *avctx, void *arg, int jobnr, int
         chroma_stride = pic->linesize[1] << 1;
     }
 
-    if (avctx->pix_fmt == AV_PIX_FMT_YUV444P10 || avctx->pix_fmt == AV_PIX_FMT_YUVA444P10) {
+    if (avctx->pix_fmt == AV_PIX_FMT_YUV444P10 || avctx->pix_fmt == AV_PIX_FMT_YUVA444P10 ||
+        avctx->pix_fmt == AV_PIX_FMT_YUV444P12 || avctx->pix_fmt == AV_PIX_FMT_YUVA444P12) {
         mb_x_shift = 5;
         log2_chroma_blocks_per_mb = 2;
     } else {
@@ -641,10 +707,15 @@ static int decode_slice_thread(AVCodecContext *avctx, void *arg, int jobnr, int
     else {
         size_t mb_max_x = slice->mb_count << (mb_x_shift - 1);
         size_t i, j;
+        if (avctx->bits_per_raw_sample == 10) {
+            val_no_chroma = 511;
+        } else { /* 12b */
+            val_no_chroma = 511 * 4;
+        }
         for (i = 0; i < 16; ++i)
             for (j = 0; j < mb_max_x; ++j) {
-                *(uint16_t*)(dest_u + (i * chroma_stride) + (j << 1)) = 511;
-                *(uint16_t*)(dest_v + (i * chroma_stride) + (j << 1)) = 511;
+                *(uint16_t*)(dest_u + (i * chroma_stride) + (j << 1)) = val_no_chroma;
+                *(uint16_t*)(dest_v + (i * chroma_stride) + (j << 1)) = val_no_chroma;
             }
     }
 
@@ -707,9 +778,6 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
     buf += frame_hdr_size;
     buf_size -= frame_hdr_size;
 
-    if ((ret = ff_thread_get_buffer(avctx, &tframe, 0)) < 0)
-        return ret;
-
  decode_picture:
     pic_size = decode_picture_header(avctx, buf, buf_size);
     if (pic_size < 0) {
@@ -717,6 +785,10 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
         return pic_size;
     }
 
+    if (ctx->first_field)
+        if ((ret = ff_thread_get_buffer(avctx, &tframe, 0)) < 0)
+            return ret;
+
     if ((ret = decode_picture(avctx)) < 0) {
         av_log(avctx, AV_LOG_ERROR, "error decoding picture\n");
         return ret;