#define LONG_BITSTREAM_READER
#include "libavutil/internal.h"
+#include "libavutil/mem_internal.h"
+
#include "avcodec.h"
#include "get_bits.h"
#include "idctdsp.h"
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) {
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;
}
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];
}
permute(ctx->qmat_chroma, ctx->prodsp.idct_permutation, ptr);
} else {
- memset(ctx->qmat_chroma, 4, 64);
+ memcpy(ctx->qmat_chroma, ctx->qmat_luma, 64);
}
return hdr_size;
}
block = blocks;
+
for (i = 0; i < 16; i++) {
memcpy(dst, block, 16 * blocks_per_slice * sizeof(*dst));
dst += dst_stride >> 1;
AVFrame *pic = ctx->frame;
int i, hdr_size, qscale, log2_chroma_blocks_per_mb;
int luma_stride, chroma_stride;
- int y_data_size, u_data_size, v_data_size, a_data_size;
- uint8_t *dest_y, *dest_u, *dest_v, *dest_a;
+ int y_data_size, u_data_size, v_data_size, a_data_size, offset;
+ uint8_t *dest_y, *dest_u, *dest_v;
LOCAL_ALIGNED_16(int16_t, qmat_luma_scaled, [64]);
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",
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 {
log2_chroma_blocks_per_mb = 1;
}
- dest_y = pic->data[0] + (slice->mb_y << 4) * luma_stride + (slice->mb_x << 5);
+ offset = (slice->mb_y << 4) * luma_stride + (slice->mb_x << 5);
+ dest_y = pic->data[0] + offset;
dest_u = pic->data[1] + (slice->mb_y << 4) * chroma_stride + (slice->mb_x << mb_x_shift);
dest_v = pic->data[2] + (slice->mb_y << 4) * chroma_stride + (slice->mb_x << mb_x_shift);
- dest_a = pic->data[3] + (slice->mb_y << 4) * luma_stride + (slice->mb_x << 5);
if (ctx->frame_type && ctx->first_field ^ ctx->frame->top_field_first) {
dest_y += pic->linesize[0];
dest_u += pic->linesize[1];
dest_v += pic->linesize[2];
- dest_a += pic->linesize[3];
+ offset += pic->linesize[3];
}
ret = decode_slice_luma(avctx, slice, (uint16_t*)dest_y, luma_stride,
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;
}
}
/* decode alpha plane if available */
- if (ctx->alpha_info && pic->data[3] && a_data_size)
+ if (ctx->alpha_info && pic->data[3] && a_data_size) {
+ uint8_t *dest_a = pic->data[3] + offset;
decode_slice_alpha(ctx, (uint16_t*)dest_a, luma_stride,
buf + y_data_size + u_data_size + v_data_size,
a_data_size, slice->mb_count);
+ }
slice->ret = 0;
return 0;
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) {
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;
return avpkt->size;
}
-#if HAVE_THREADS
-static int decode_init_thread_copy(AVCodecContext *avctx)
-{
- ProresContext *ctx = avctx->priv_data;
-
- ctx->slices = NULL;
-
- return 0;
-}
-#endif
-
static av_cold int decode_close(AVCodecContext *avctx)
{
ProresContext *ctx = avctx->priv_data;
AVCodec ff_prores_decoder = {
.name = "prores",
- .long_name = NULL_IF_CONFIG_SMALL("ProRes (iCodec Pro)"),
+ .long_name = NULL_IF_CONFIG_SMALL("Apple ProRes (iCodec Pro)"),
.type = AVMEDIA_TYPE_VIDEO,
.id = AV_CODEC_ID_PRORES,
.priv_data_size = sizeof(ProresContext),
.init = decode_init,
- .init_thread_copy = ONLY_IF_THREADS_ENABLED(decode_init_thread_copy),
.close = decode_close,
.decode = decode_frame,
.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SLICE_THREADS | AV_CODEC_CAP_FRAME_THREADS,