mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2026-08-09 09:32:43 +00:00
lavc: Split out common components used by vulkan prores encoder
This commit is contained in:
@@ -647,7 +647,7 @@ OBJS-$(CONFIG_PPM_ENCODER) += pnmenc.o
|
||||
OBJS-$(CONFIG_PRORES_DECODER) += proresdec.o proresdsp.o proresdata.o
|
||||
OBJS-$(CONFIG_PRORES_ENCODER) += proresenc_anatoliy.o proresdata.o
|
||||
OBJS-$(CONFIG_PRORES_AW_ENCODER) += proresenc_anatoliy.o proresdata.o
|
||||
OBJS-$(CONFIG_PRORES_KS_ENCODER) += proresenc_kostya.o proresdata.o
|
||||
OBJS-$(CONFIG_PRORES_KS_ENCODER) += proresenc_kostya.o proresdata.o proresenc_kostya_common.o
|
||||
OBJS-$(CONFIG_PRORES_RAW_DECODER) += prores_raw.o proresdsp.o proresdata.o
|
||||
OBJS-$(CONFIG_PRORES_VIDEOTOOLBOX_ENCODER) += videotoolboxenc.o
|
||||
OBJS-$(CONFIG_PROSUMER_DECODER) += prosumer.o
|
||||
|
||||
@@ -33,179 +33,7 @@
|
||||
#include "profiles.h"
|
||||
#include "bytestream.h"
|
||||
#include "proresdata.h"
|
||||
|
||||
#define CFACTOR_Y422 2
|
||||
#define CFACTOR_Y444 3
|
||||
|
||||
#define MAX_MBS_PER_SLICE 8
|
||||
|
||||
#define MAX_PLANES 4
|
||||
|
||||
enum {
|
||||
PRORES_PROFILE_AUTO = -1,
|
||||
PRORES_PROFILE_PROXY = 0,
|
||||
PRORES_PROFILE_LT,
|
||||
PRORES_PROFILE_STANDARD,
|
||||
PRORES_PROFILE_HQ,
|
||||
PRORES_PROFILE_4444,
|
||||
PRORES_PROFILE_4444XQ,
|
||||
};
|
||||
|
||||
enum {
|
||||
QUANT_MAT_PROXY = 0,
|
||||
QUANT_MAT_PROXY_CHROMA,
|
||||
QUANT_MAT_LT,
|
||||
QUANT_MAT_STANDARD,
|
||||
QUANT_MAT_HQ,
|
||||
QUANT_MAT_XQ_LUMA,
|
||||
QUANT_MAT_DEFAULT,
|
||||
};
|
||||
|
||||
static const uint8_t prores_quant_matrices[][64] = {
|
||||
{ // proxy
|
||||
4, 7, 9, 11, 13, 14, 15, 63,
|
||||
7, 7, 11, 12, 14, 15, 63, 63,
|
||||
9, 11, 13, 14, 15, 63, 63, 63,
|
||||
11, 11, 13, 14, 63, 63, 63, 63,
|
||||
11, 13, 14, 63, 63, 63, 63, 63,
|
||||
13, 14, 63, 63, 63, 63, 63, 63,
|
||||
13, 63, 63, 63, 63, 63, 63, 63,
|
||||
63, 63, 63, 63, 63, 63, 63, 63,
|
||||
},
|
||||
{ // proxy chromas
|
||||
4, 7, 9, 11, 13, 14, 63, 63,
|
||||
7, 7, 11, 12, 14, 63, 63, 63,
|
||||
9, 11, 13, 14, 63, 63, 63, 63,
|
||||
11, 11, 13, 14, 63, 63, 63, 63,
|
||||
11, 13, 14, 63, 63, 63, 63, 63,
|
||||
13, 14, 63, 63, 63, 63, 63, 63,
|
||||
13, 63, 63, 63, 63, 63, 63, 63,
|
||||
63, 63, 63, 63, 63, 63, 63, 63
|
||||
},
|
||||
{ // LT
|
||||
4, 5, 6, 7, 9, 11, 13, 15,
|
||||
5, 5, 7, 8, 11, 13, 15, 17,
|
||||
6, 7, 9, 11, 13, 15, 15, 17,
|
||||
7, 7, 9, 11, 13, 15, 17, 19,
|
||||
7, 9, 11, 13, 14, 16, 19, 23,
|
||||
9, 11, 13, 14, 16, 19, 23, 29,
|
||||
9, 11, 13, 15, 17, 21, 28, 35,
|
||||
11, 13, 16, 17, 21, 28, 35, 41,
|
||||
},
|
||||
{ // standard
|
||||
4, 4, 5, 5, 6, 7, 7, 9,
|
||||
4, 4, 5, 6, 7, 7, 9, 9,
|
||||
5, 5, 6, 7, 7, 9, 9, 10,
|
||||
5, 5, 6, 7, 7, 9, 9, 10,
|
||||
5, 6, 7, 7, 8, 9, 10, 12,
|
||||
6, 7, 7, 8, 9, 10, 12, 15,
|
||||
6, 7, 7, 9, 10, 11, 14, 17,
|
||||
7, 7, 9, 10, 11, 14, 17, 21,
|
||||
},
|
||||
{ // high quality
|
||||
4, 4, 4, 4, 4, 4, 4, 4,
|
||||
4, 4, 4, 4, 4, 4, 4, 4,
|
||||
4, 4, 4, 4, 4, 4, 4, 4,
|
||||
4, 4, 4, 4, 4, 4, 4, 5,
|
||||
4, 4, 4, 4, 4, 4, 5, 5,
|
||||
4, 4, 4, 4, 4, 5, 5, 6,
|
||||
4, 4, 4, 4, 5, 5, 6, 7,
|
||||
4, 4, 4, 4, 5, 6, 7, 7,
|
||||
},
|
||||
{ // XQ luma
|
||||
2, 2, 2, 2, 2, 2, 2, 2,
|
||||
2, 2, 2, 2, 2, 2, 2, 2,
|
||||
2, 2, 2, 2, 2, 2, 2, 2,
|
||||
2, 2, 2, 2, 2, 2, 2, 3,
|
||||
2, 2, 2, 2, 2, 2, 3, 3,
|
||||
2, 2, 2, 2, 2, 3, 3, 3,
|
||||
2, 2, 2, 2, 3, 3, 3, 4,
|
||||
2, 2, 2, 2, 3, 3, 4, 4,
|
||||
},
|
||||
{ // codec default
|
||||
4, 4, 4, 4, 4, 4, 4, 4,
|
||||
4, 4, 4, 4, 4, 4, 4, 4,
|
||||
4, 4, 4, 4, 4, 4, 4, 4,
|
||||
4, 4, 4, 4, 4, 4, 4, 4,
|
||||
4, 4, 4, 4, 4, 4, 4, 4,
|
||||
4, 4, 4, 4, 4, 4, 4, 4,
|
||||
4, 4, 4, 4, 4, 4, 4, 4,
|
||||
4, 4, 4, 4, 4, 4, 4, 4,
|
||||
},
|
||||
};
|
||||
|
||||
#define NUM_MB_LIMITS 4
|
||||
static const int prores_mb_limits[NUM_MB_LIMITS] = {
|
||||
1620, // up to 720x576
|
||||
2700, // up to 960x720
|
||||
6075, // up to 1440x1080
|
||||
9216, // up to 2048x1152
|
||||
};
|
||||
|
||||
static const struct prores_profile {
|
||||
const char *full_name;
|
||||
uint32_t tag;
|
||||
int min_quant;
|
||||
int max_quant;
|
||||
int br_tab[NUM_MB_LIMITS];
|
||||
int quant;
|
||||
int quant_chroma;
|
||||
} prores_profile_info[6] = {
|
||||
{
|
||||
.full_name = "proxy",
|
||||
.tag = MKTAG('a', 'p', 'c', 'o'),
|
||||
.min_quant = 4,
|
||||
.max_quant = 8,
|
||||
.br_tab = { 300, 242, 220, 194 },
|
||||
.quant = QUANT_MAT_PROXY,
|
||||
.quant_chroma = QUANT_MAT_PROXY_CHROMA,
|
||||
},
|
||||
{
|
||||
.full_name = "LT",
|
||||
.tag = MKTAG('a', 'p', 'c', 's'),
|
||||
.min_quant = 1,
|
||||
.max_quant = 9,
|
||||
.br_tab = { 720, 560, 490, 440 },
|
||||
.quant = QUANT_MAT_LT,
|
||||
.quant_chroma = QUANT_MAT_LT,
|
||||
},
|
||||
{
|
||||
.full_name = "standard",
|
||||
.tag = MKTAG('a', 'p', 'c', 'n'),
|
||||
.min_quant = 1,
|
||||
.max_quant = 6,
|
||||
.br_tab = { 1050, 808, 710, 632 },
|
||||
.quant = QUANT_MAT_STANDARD,
|
||||
.quant_chroma = QUANT_MAT_STANDARD,
|
||||
},
|
||||
{
|
||||
.full_name = "high quality",
|
||||
.tag = MKTAG('a', 'p', 'c', 'h'),
|
||||
.min_quant = 1,
|
||||
.max_quant = 6,
|
||||
.br_tab = { 1566, 1216, 1070, 950 },
|
||||
.quant = QUANT_MAT_HQ,
|
||||
.quant_chroma = QUANT_MAT_HQ,
|
||||
},
|
||||
{
|
||||
.full_name = "4444",
|
||||
.tag = MKTAG('a', 'p', '4', 'h'),
|
||||
.min_quant = 1,
|
||||
.max_quant = 6,
|
||||
.br_tab = { 2350, 1828, 1600, 1425 },
|
||||
.quant = QUANT_MAT_HQ,
|
||||
.quant_chroma = QUANT_MAT_HQ,
|
||||
},
|
||||
{
|
||||
.full_name = "4444XQ",
|
||||
.tag = MKTAG('a', 'p', '4', 'x'),
|
||||
.min_quant = 1,
|
||||
.max_quant = 6,
|
||||
.br_tab = { 3525, 2742, 2400, 2137 },
|
||||
.quant = QUANT_MAT_HQ, /* Fix me : use QUANT_MAT_XQ_LUMA */
|
||||
.quant_chroma = QUANT_MAT_HQ,
|
||||
}
|
||||
};
|
||||
#include "proresenc_kostya_common.h"
|
||||
|
||||
#define TRELLIS_WIDTH 16
|
||||
#define SCORE_LIMIT INT_MAX / 2
|
||||
@@ -217,8 +45,6 @@ struct TrellisNode {
|
||||
int score;
|
||||
};
|
||||
|
||||
#define MAX_STORED_Q 16
|
||||
|
||||
typedef struct ProresThreadData {
|
||||
DECLARE_ALIGNED(16, int16_t, blocks)[MAX_PLANES][64 * 4 * MAX_MBS_PER_SLICE];
|
||||
DECLARE_ALIGNED(16, uint16_t, emu_buf)[16 * 16];
|
||||
@@ -227,49 +53,6 @@ typedef struct ProresThreadData {
|
||||
struct TrellisNode *nodes;
|
||||
} ProresThreadData;
|
||||
|
||||
typedef struct ProresContext {
|
||||
AVClass *class;
|
||||
DECLARE_ALIGNED(16, int16_t, blocks)[MAX_PLANES][64 * 4 * MAX_MBS_PER_SLICE];
|
||||
DECLARE_ALIGNED(16, uint16_t, emu_buf)[16*16];
|
||||
int16_t quants[MAX_STORED_Q][64];
|
||||
int16_t quants_chroma[MAX_STORED_Q][64];
|
||||
int16_t custom_q[64];
|
||||
int16_t custom_chroma_q[64];
|
||||
const uint8_t *quant_mat;
|
||||
const uint8_t *quant_chroma_mat;
|
||||
const uint8_t *scantable;
|
||||
|
||||
void (*fdct)(FDCTDSPContext *fdsp, const uint16_t *src,
|
||||
ptrdiff_t linesize, int16_t *block);
|
||||
FDCTDSPContext fdsp;
|
||||
|
||||
const AVFrame *pic;
|
||||
int mb_width, mb_height;
|
||||
int mbs_per_slice;
|
||||
int num_chroma_blocks, chroma_factor;
|
||||
int slices_width;
|
||||
int slices_per_picture;
|
||||
int pictures_per_frame; // 1 for progressive, 2 for interlaced
|
||||
int cur_picture_idx;
|
||||
int num_planes;
|
||||
int bits_per_mb;
|
||||
int force_quant;
|
||||
int alpha_bits;
|
||||
int warn;
|
||||
|
||||
char *vendor;
|
||||
int quant_sel;
|
||||
|
||||
int frame_size_upper_bound;
|
||||
|
||||
int profile;
|
||||
const struct prores_profile *profile_info;
|
||||
|
||||
int *slice_q;
|
||||
|
||||
ProresThreadData *tdata;
|
||||
} ProresContext;
|
||||
|
||||
static void get_slice_data(ProresContext *ctx, const uint16_t *src,
|
||||
ptrdiff_t linesize, int x, int y, int w, int h,
|
||||
int16_t *blocks, uint16_t *emu_buf,
|
||||
@@ -437,7 +220,6 @@ static void encode_acs(PutBitContext *pb, int16_t *blocks,
|
||||
int prev_level = 2;
|
||||
int run = 0, level;
|
||||
int max_coeffs, abs_level;
|
||||
|
||||
max_coeffs = blocks_per_slice << 6;
|
||||
|
||||
for (i = 1; i < 64; i++) {
|
||||
@@ -685,7 +467,6 @@ static int estimate_acs(int *error, int16_t *blocks, int blocks_per_slice,
|
||||
bits += estimate_vlc(ff_prores_run_to_cb[prev_run], run);
|
||||
bits += estimate_vlc(ff_prores_level_to_cb[prev_level],
|
||||
abs_level - 1) + 1;
|
||||
|
||||
prev_run = FFMIN(run, 15);
|
||||
prev_level = FFMIN(abs_level, 9);
|
||||
run = 0;
|
||||
@@ -905,7 +686,6 @@ static int find_slice_quant(AVCodecContext *avctx,
|
||||
|
||||
for (q = min_quant; q < max_quant + 2; q++) {
|
||||
cur = trellis_node + q;
|
||||
|
||||
bits = td->nodes[prev].bits + slice_bits[q];
|
||||
error = slice_score[q];
|
||||
if (bits > bits_limit)
|
||||
@@ -970,7 +750,7 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt,
|
||||
PutBitContext pb;
|
||||
int x, y, i, mb, q = 0;
|
||||
int sizes[4] = { 0 };
|
||||
int slice_hdr_size = 2 + 2 * (ctx->num_planes - 1);
|
||||
int slice_hdr_size = 2 * ctx->num_planes;
|
||||
int frame_size, picture_size, slice_size;
|
||||
int pkt_size, ret;
|
||||
int max_slice_size = (ctx->frame_size_upper_bound - 200) / (ctx->pictures_per_frame * ctx->slices_per_picture + 1);
|
||||
@@ -1076,7 +856,6 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt,
|
||||
return ret;
|
||||
|
||||
pkt_size += delta;
|
||||
// restore pointers
|
||||
orig_buf = pkt->data + (orig_buf - start);
|
||||
buf = pkt->data + (buf - start);
|
||||
picture_size_pos = pkt->data + (picture_size_pos - start);
|
||||
@@ -1149,105 +928,18 @@ static void prores_fdct(FDCTDSPContext *fdsp, const uint16_t *src,
|
||||
static av_cold int encode_init(AVCodecContext *avctx)
|
||||
{
|
||||
ProresContext *ctx = avctx->priv_data;
|
||||
int mps;
|
||||
int i, j;
|
||||
int min_quant, max_quant;
|
||||
int interlaced = !!(avctx->flags & AV_CODEC_FLAG_INTERLACED_DCT);
|
||||
int err = 0, i, j, min_quant, max_quant;
|
||||
|
||||
avctx->bits_per_raw_sample = 10;
|
||||
err = ff_prores_kostya_encode_init(avctx, ctx, avctx->pix_fmt);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
ctx->fdct = prores_fdct;
|
||||
ctx->scantable = interlaced ? ff_prores_interlaced_scan
|
||||
: ff_prores_progressive_scan;
|
||||
ff_fdctdsp_init(&ctx->fdsp, avctx);
|
||||
|
||||
mps = ctx->mbs_per_slice;
|
||||
if (mps & (mps - 1)) {
|
||||
av_log(avctx, AV_LOG_ERROR,
|
||||
"there should be an integer power of two MBs per slice\n");
|
||||
return AVERROR(EINVAL);
|
||||
}
|
||||
if (ctx->profile == PRORES_PROFILE_AUTO) {
|
||||
const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(avctx->pix_fmt);
|
||||
ctx->profile = (desc->flags & AV_PIX_FMT_FLAG_ALPHA ||
|
||||
!(desc->log2_chroma_w + desc->log2_chroma_h))
|
||||
? PRORES_PROFILE_4444 : PRORES_PROFILE_HQ;
|
||||
av_log(avctx, AV_LOG_INFO, "Autoselected %s. It can be overridden "
|
||||
"through -profile option.\n", ctx->profile == PRORES_PROFILE_4444
|
||||
? "4:4:4:4 profile because of the used input colorspace"
|
||||
: "HQ profile to keep best quality");
|
||||
}
|
||||
if (av_pix_fmt_desc_get(avctx->pix_fmt)->flags & AV_PIX_FMT_FLAG_ALPHA) {
|
||||
if (ctx->profile != PRORES_PROFILE_4444 &&
|
||||
ctx->profile != PRORES_PROFILE_4444XQ) {
|
||||
// force alpha and warn
|
||||
av_log(avctx, AV_LOG_WARNING, "Profile selected will not "
|
||||
"encode alpha. Override with -profile if needed.\n");
|
||||
ctx->alpha_bits = 0;
|
||||
}
|
||||
if (ctx->alpha_bits & 7) {
|
||||
av_log(avctx, AV_LOG_ERROR, "alpha bits should be 0, 8 or 16\n");
|
||||
return AVERROR(EINVAL);
|
||||
}
|
||||
avctx->bits_per_coded_sample = 32;
|
||||
} else {
|
||||
ctx->alpha_bits = 0;
|
||||
}
|
||||
|
||||
ctx->chroma_factor = avctx->pix_fmt == AV_PIX_FMT_YUV422P10
|
||||
? CFACTOR_Y422
|
||||
: CFACTOR_Y444;
|
||||
ctx->profile_info = prores_profile_info + ctx->profile;
|
||||
ctx->num_planes = 3 + !!ctx->alpha_bits;
|
||||
|
||||
ctx->mb_width = FFALIGN(avctx->width, 16) >> 4;
|
||||
|
||||
if (interlaced)
|
||||
ctx->mb_height = FFALIGN(avctx->height, 32) >> 5;
|
||||
else
|
||||
ctx->mb_height = FFALIGN(avctx->height, 16) >> 4;
|
||||
|
||||
ctx->slices_width = ctx->mb_width / mps;
|
||||
ctx->slices_width += av_popcount(ctx->mb_width - ctx->slices_width * mps);
|
||||
ctx->slices_per_picture = ctx->mb_height * ctx->slices_width;
|
||||
ctx->pictures_per_frame = 1 + interlaced;
|
||||
|
||||
if (ctx->quant_sel == -1) {
|
||||
ctx->quant_mat = prores_quant_matrices[ctx->profile_info->quant];
|
||||
ctx->quant_chroma_mat = prores_quant_matrices[ctx->profile_info->quant_chroma];
|
||||
} else {
|
||||
ctx->quant_mat = prores_quant_matrices[ctx->quant_sel];
|
||||
ctx->quant_chroma_mat = prores_quant_matrices[ctx->quant_sel];
|
||||
}
|
||||
|
||||
if (strlen(ctx->vendor) != 4) {
|
||||
av_log(avctx, AV_LOG_ERROR, "vendor ID should be 4 bytes\n");
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
|
||||
ctx->force_quant = avctx->global_quality / FF_QP2LAMBDA;
|
||||
if (!ctx->force_quant) {
|
||||
if (!ctx->bits_per_mb) {
|
||||
for (i = 0; i < NUM_MB_LIMITS - 1; i++)
|
||||
if (prores_mb_limits[i] >= ctx->mb_width * ctx->mb_height *
|
||||
ctx->pictures_per_frame)
|
||||
break;
|
||||
ctx->bits_per_mb = ctx->profile_info->br_tab[i];
|
||||
if (ctx->alpha_bits)
|
||||
ctx->bits_per_mb *= 20;
|
||||
} else if (ctx->bits_per_mb < 128) {
|
||||
av_log(avctx, AV_LOG_ERROR, "too few bits per MB, please set at least 128\n");
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
|
||||
min_quant = ctx->profile_info->min_quant;
|
||||
max_quant = ctx->profile_info->max_quant;
|
||||
for (i = min_quant; i < MAX_STORED_Q; i++) {
|
||||
for (j = 0; j < 64; j++) {
|
||||
ctx->quants[i][j] = ctx->quant_mat[j] * i;
|
||||
ctx->quants_chroma[i][j] = ctx->quant_chroma_mat[j] * i;
|
||||
}
|
||||
}
|
||||
|
||||
ctx->slice_q = av_malloc_array(ctx->slices_per_picture, sizeof(*ctx->slice_q));
|
||||
if (!ctx->slice_q)
|
||||
@@ -1269,51 +961,8 @@ static av_cold int encode_init(AVCodecContext *avctx)
|
||||
ctx->tdata[j].nodes[i].score = 0;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
int ls = 0;
|
||||
int ls_chroma = 0;
|
||||
|
||||
if (ctx->force_quant > 64) {
|
||||
av_log(avctx, AV_LOG_ERROR, "too large quantiser, maximum is 64\n");
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
|
||||
for (j = 0; j < 64; j++) {
|
||||
ctx->quants[0][j] = ctx->quant_mat[j] * ctx->force_quant;
|
||||
ctx->quants_chroma[0][j] = ctx->quant_chroma_mat[j] * ctx->force_quant;
|
||||
ls += av_log2((1 << 11) / ctx->quants[0][j]) * 2 + 1;
|
||||
ls_chroma += av_log2((1 << 11) / ctx->quants_chroma[0][j]) * 2 + 1;
|
||||
}
|
||||
|
||||
ctx->bits_per_mb = ls * 4 + ls_chroma * 4;
|
||||
if (ctx->chroma_factor == CFACTOR_Y444)
|
||||
ctx->bits_per_mb += ls_chroma * 4;
|
||||
}
|
||||
|
||||
ctx->frame_size_upper_bound = (ctx->pictures_per_frame *
|
||||
ctx->slices_per_picture + 1) *
|
||||
(2 + 2 * ctx->num_planes +
|
||||
(mps * ctx->bits_per_mb) / 8)
|
||||
+ 200;
|
||||
|
||||
if (ctx->alpha_bits) {
|
||||
// The alpha plane is run-coded and might exceed the bit budget.
|
||||
ctx->frame_size_upper_bound += (ctx->pictures_per_frame *
|
||||
ctx->slices_per_picture + 1) *
|
||||
/* num pixels per slice */ (ctx->mbs_per_slice * 256 *
|
||||
/* bits per pixel */ (1 + ctx->alpha_bits + 1) + 7 >> 3);
|
||||
}
|
||||
|
||||
avctx->codec_tag = ctx->profile_info->tag;
|
||||
avctx->profile = ctx->profile;
|
||||
|
||||
av_log(avctx, AV_LOG_DEBUG,
|
||||
"profile %d, %d slices, interlacing: %s, %d bits per MB\n",
|
||||
ctx->profile, ctx->slices_per_picture * ctx->pictures_per_frame,
|
||||
interlaced ? "yes" : "no", ctx->bits_per_mb);
|
||||
av_log(avctx, AV_LOG_DEBUG, "frame size upper bound: %d\n",
|
||||
ctx->frame_size_upper_bound);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
364
libavcodec/proresenc_kostya_common.c
Normal file
364
libavcodec/proresenc_kostya_common.c
Normal file
@@ -0,0 +1,364 @@
|
||||
/*
|
||||
* Apple ProRes encoder
|
||||
*
|
||||
* Copyright (c) 2011 Anatoliy Wasserman
|
||||
* Copyright (c) 2012 Konstantin Shishkov
|
||||
*
|
||||
* 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 "libavutil/pixdesc.h"
|
||||
#include "avcodec.h"
|
||||
#include "bytestream.h"
|
||||
#include "proresdata.h"
|
||||
#include <sys/types.h>
|
||||
#include "proresenc_kostya_common.h"
|
||||
|
||||
static const uint8_t prores_quant_matrices[][64] = {
|
||||
{ // proxy
|
||||
4, 7, 9, 11, 13, 14, 15, 63,
|
||||
7, 7, 11, 12, 14, 15, 63, 63,
|
||||
9, 11, 13, 14, 15, 63, 63, 63,
|
||||
11, 11, 13, 14, 63, 63, 63, 63,
|
||||
11, 13, 14, 63, 63, 63, 63, 63,
|
||||
13, 14, 63, 63, 63, 63, 63, 63,
|
||||
13, 63, 63, 63, 63, 63, 63, 63,
|
||||
63, 63, 63, 63, 63, 63, 63, 63,
|
||||
},
|
||||
{ // proxy chromas
|
||||
4, 7, 9, 11, 13, 14, 63, 63,
|
||||
7, 7, 11, 12, 14, 63, 63, 63,
|
||||
9, 11, 13, 14, 63, 63, 63, 63,
|
||||
11, 11, 13, 14, 63, 63, 63, 63,
|
||||
11, 13, 14, 63, 63, 63, 63, 63,
|
||||
13, 14, 63, 63, 63, 63, 63, 63,
|
||||
13, 63, 63, 63, 63, 63, 63, 63,
|
||||
63, 63, 63, 63, 63, 63, 63, 63
|
||||
},
|
||||
{ // LT
|
||||
4, 5, 6, 7, 9, 11, 13, 15,
|
||||
5, 5, 7, 8, 11, 13, 15, 17,
|
||||
6, 7, 9, 11, 13, 15, 15, 17,
|
||||
7, 7, 9, 11, 13, 15, 17, 19,
|
||||
7, 9, 11, 13, 14, 16, 19, 23,
|
||||
9, 11, 13, 14, 16, 19, 23, 29,
|
||||
9, 11, 13, 15, 17, 21, 28, 35,
|
||||
11, 13, 16, 17, 21, 28, 35, 41,
|
||||
},
|
||||
{ // standard
|
||||
4, 4, 5, 5, 6, 7, 7, 9,
|
||||
4, 4, 5, 6, 7, 7, 9, 9,
|
||||
5, 5, 6, 7, 7, 9, 9, 10,
|
||||
5, 5, 6, 7, 7, 9, 9, 10,
|
||||
5, 6, 7, 7, 8, 9, 10, 12,
|
||||
6, 7, 7, 8, 9, 10, 12, 15,
|
||||
6, 7, 7, 9, 10, 11, 14, 17,
|
||||
7, 7, 9, 10, 11, 14, 17, 21,
|
||||
},
|
||||
{ // high quality
|
||||
4, 4, 4, 4, 4, 4, 4, 4,
|
||||
4, 4, 4, 4, 4, 4, 4, 4,
|
||||
4, 4, 4, 4, 4, 4, 4, 4,
|
||||
4, 4, 4, 4, 4, 4, 4, 5,
|
||||
4, 4, 4, 4, 4, 4, 5, 5,
|
||||
4, 4, 4, 4, 4, 5, 5, 6,
|
||||
4, 4, 4, 4, 5, 5, 6, 7,
|
||||
4, 4, 4, 4, 5, 6, 7, 7,
|
||||
},
|
||||
{ // XQ luma
|
||||
2, 2, 2, 2, 2, 2, 2, 2,
|
||||
2, 2, 2, 2, 2, 2, 2, 2,
|
||||
2, 2, 2, 2, 2, 2, 2, 2,
|
||||
2, 2, 2, 2, 2, 2, 2, 3,
|
||||
2, 2, 2, 2, 2, 2, 3, 3,
|
||||
2, 2, 2, 2, 2, 3, 3, 3,
|
||||
2, 2, 2, 2, 3, 3, 3, 4,
|
||||
2, 2, 2, 2, 3, 3, 4, 4,
|
||||
},
|
||||
{ // codec default
|
||||
4, 4, 4, 4, 4, 4, 4, 4,
|
||||
4, 4, 4, 4, 4, 4, 4, 4,
|
||||
4, 4, 4, 4, 4, 4, 4, 4,
|
||||
4, 4, 4, 4, 4, 4, 4, 4,
|
||||
4, 4, 4, 4, 4, 4, 4, 4,
|
||||
4, 4, 4, 4, 4, 4, 4, 4,
|
||||
4, 4, 4, 4, 4, 4, 4, 4,
|
||||
4, 4, 4, 4, 4, 4, 4, 4,
|
||||
},
|
||||
};
|
||||
|
||||
static const int prores_mb_limits[NUM_MB_LIMITS] = {
|
||||
1620, // up to 720x576
|
||||
2700, // up to 960x720
|
||||
6075, // up to 1440x1080
|
||||
9216, // up to 2048x1152
|
||||
};
|
||||
|
||||
static const prores_profile prores_profile_info[6] = {
|
||||
{
|
||||
.full_name = "proxy",
|
||||
.tag = MKTAG('a', 'p', 'c', 'o'),
|
||||
.min_quant = 4,
|
||||
.max_quant = 8,
|
||||
.br_tab = { 300, 242, 220, 194 },
|
||||
.quant = QUANT_MAT_PROXY,
|
||||
.quant_chroma = QUANT_MAT_PROXY_CHROMA,
|
||||
},
|
||||
{
|
||||
.full_name = "LT",
|
||||
.tag = MKTAG('a', 'p', 'c', 's'),
|
||||
.min_quant = 1,
|
||||
.max_quant = 9,
|
||||
.br_tab = { 720, 560, 490, 440 },
|
||||
.quant = QUANT_MAT_LT,
|
||||
.quant_chroma = QUANT_MAT_LT,
|
||||
},
|
||||
{
|
||||
.full_name = "standard",
|
||||
.tag = MKTAG('a', 'p', 'c', 'n'),
|
||||
.min_quant = 1,
|
||||
.max_quant = 6,
|
||||
.br_tab = { 1050, 808, 710, 632 },
|
||||
.quant = QUANT_MAT_STANDARD,
|
||||
.quant_chroma = QUANT_MAT_STANDARD,
|
||||
},
|
||||
{
|
||||
.full_name = "high quality",
|
||||
.tag = MKTAG('a', 'p', 'c', 'h'),
|
||||
.min_quant = 1,
|
||||
.max_quant = 6,
|
||||
.br_tab = { 1566, 1216, 1070, 950 },
|
||||
.quant = QUANT_MAT_HQ,
|
||||
.quant_chroma = QUANT_MAT_HQ,
|
||||
},
|
||||
{
|
||||
.full_name = "4444",
|
||||
.tag = MKTAG('a', 'p', '4', 'h'),
|
||||
.min_quant = 1,
|
||||
.max_quant = 6,
|
||||
.br_tab = { 2350, 1828, 1600, 1425 },
|
||||
.quant = QUANT_MAT_HQ,
|
||||
.quant_chroma = QUANT_MAT_HQ,
|
||||
},
|
||||
{
|
||||
.full_name = "4444XQ",
|
||||
.tag = MKTAG('a', 'p', '4', 'x'),
|
||||
.min_quant = 1,
|
||||
.max_quant = 6,
|
||||
.br_tab = { 3525, 2742, 2400, 2137 },
|
||||
.quant = QUANT_MAT_HQ, /* Fix me : use QUANT_MAT_XQ_LUMA */
|
||||
.quant_chroma = QUANT_MAT_HQ,
|
||||
}
|
||||
};
|
||||
|
||||
av_cold int ff_prores_kostya_encode_init(AVCodecContext *avctx, ProresContext *ctx,
|
||||
enum AVPixelFormat pix_fmt)
|
||||
{
|
||||
int mps, i, j, min_quant;
|
||||
int interlaced = !!(avctx->flags & AV_CODEC_FLAG_INTERLACED_DCT);
|
||||
|
||||
avctx->bits_per_raw_sample = 10;
|
||||
|
||||
ctx->scantable = interlaced ? ff_prores_interlaced_scan
|
||||
: ff_prores_progressive_scan;
|
||||
|
||||
mps = ctx->mbs_per_slice;
|
||||
if (mps & (mps - 1)) {
|
||||
av_log(avctx, AV_LOG_ERROR,
|
||||
"there should be an integer power of two MBs per slice\n");
|
||||
return AVERROR(EINVAL);
|
||||
}
|
||||
if (ctx->profile == PRORES_PROFILE_AUTO) {
|
||||
const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt);
|
||||
ctx->profile = (desc->flags & AV_PIX_FMT_FLAG_ALPHA ||
|
||||
!(desc->log2_chroma_w + desc->log2_chroma_h))
|
||||
? PRORES_PROFILE_4444 : PRORES_PROFILE_HQ;
|
||||
av_log(avctx, AV_LOG_INFO, "Autoselected %s. It can be overridden "
|
||||
"through -profile option.\n", ctx->profile == PRORES_PROFILE_4444
|
||||
? "4:4:4:4 profile because of the used input colorspace"
|
||||
: "HQ profile to keep best quality");
|
||||
}
|
||||
if (av_pix_fmt_desc_get(pix_fmt)->flags & AV_PIX_FMT_FLAG_ALPHA) {
|
||||
if (ctx->profile != PRORES_PROFILE_4444 &&
|
||||
ctx->profile != PRORES_PROFILE_4444XQ) {
|
||||
// force alpha and warn
|
||||
av_log(avctx, AV_LOG_WARNING, "Profile selected will not "
|
||||
"encode alpha. Override with -profile if needed.\n");
|
||||
ctx->alpha_bits = 0;
|
||||
}
|
||||
if (ctx->alpha_bits & 7) {
|
||||
av_log(avctx, AV_LOG_ERROR, "alpha bits should be 0, 8 or 16\n");
|
||||
return AVERROR(EINVAL);
|
||||
}
|
||||
avctx->bits_per_coded_sample = 32;
|
||||
} else {
|
||||
ctx->alpha_bits = 0;
|
||||
}
|
||||
|
||||
ctx->chroma_factor = pix_fmt == AV_PIX_FMT_YUV422P10
|
||||
? CFACTOR_Y422
|
||||
: CFACTOR_Y444;
|
||||
ctx->profile_info = prores_profile_info + ctx->profile;
|
||||
ctx->num_planes = 3 + !!ctx->alpha_bits;
|
||||
|
||||
ctx->mb_width = FFALIGN(avctx->width, 16) >> 4;
|
||||
|
||||
if (interlaced)
|
||||
ctx->mb_height = FFALIGN(avctx->height, 32) >> 5;
|
||||
else
|
||||
ctx->mb_height = FFALIGN(avctx->height, 16) >> 4;
|
||||
|
||||
ctx->slices_width = ctx->mb_width / mps;
|
||||
ctx->slices_width += av_popcount(ctx->mb_width - ctx->slices_width * mps);
|
||||
ctx->slices_per_picture = ctx->mb_height * ctx->slices_width;
|
||||
ctx->pictures_per_frame = 1 + interlaced;
|
||||
|
||||
if (ctx->quant_sel == -1) {
|
||||
ctx->quant_mat = prores_quant_matrices[ctx->profile_info->quant];
|
||||
ctx->quant_chroma_mat = prores_quant_matrices[ctx->profile_info->quant_chroma];
|
||||
} else {
|
||||
ctx->quant_mat = prores_quant_matrices[ctx->quant_sel];
|
||||
ctx->quant_chroma_mat = prores_quant_matrices[ctx->quant_sel];
|
||||
}
|
||||
|
||||
if (strlen(ctx->vendor) != 4) {
|
||||
av_log(avctx, AV_LOG_ERROR, "vendor ID should be 4 bytes\n");
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
|
||||
ctx->force_quant = avctx->global_quality / FF_QP2LAMBDA;
|
||||
if (!ctx->force_quant) {
|
||||
if (!ctx->bits_per_mb) {
|
||||
for (i = 0; i < NUM_MB_LIMITS - 1; i++)
|
||||
if (prores_mb_limits[i] >= ctx->mb_width * ctx->mb_height *
|
||||
ctx->pictures_per_frame)
|
||||
break;
|
||||
ctx->bits_per_mb = ctx->profile_info->br_tab[i];
|
||||
if (ctx->alpha_bits)
|
||||
ctx->bits_per_mb *= 20;
|
||||
} else if (ctx->bits_per_mb < 128) {
|
||||
av_log(avctx, AV_LOG_ERROR, "too few bits per MB, please set at least 128\n");
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
|
||||
min_quant = ctx->profile_info->min_quant;
|
||||
for (i = min_quant; i < MAX_STORED_Q; i++) {
|
||||
for (j = 0; j < 64; j++) {
|
||||
ctx->quants[i][j] = ctx->quant_mat[j] * i;
|
||||
ctx->quants_chroma[i][j] = ctx->quant_chroma_mat[j] * i;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
int ls = 0;
|
||||
int ls_chroma = 0;
|
||||
|
||||
if (ctx->force_quant > 64) {
|
||||
av_log(avctx, AV_LOG_ERROR, "too large quantiser, maximum is 64\n");
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
|
||||
for (j = 0; j < 64; j++) {
|
||||
ctx->quants[0][j] = ctx->quant_mat[j] * ctx->force_quant;
|
||||
ctx->quants_chroma[0][j] = ctx->quant_chroma_mat[j] * ctx->force_quant;
|
||||
ls += av_log2((1 << 11) / ctx->quants[0][j]) * 2 + 1;
|
||||
ls_chroma += av_log2((1 << 11) / ctx->quants_chroma[0][j]) * 2 + 1;
|
||||
}
|
||||
|
||||
ctx->bits_per_mb = ls * 4 + ls_chroma * 4;
|
||||
if (ctx->chroma_factor == CFACTOR_Y444)
|
||||
ctx->bits_per_mb += ls_chroma * 4;
|
||||
}
|
||||
|
||||
ctx->frame_size_upper_bound = (ctx->pictures_per_frame *
|
||||
ctx->slices_per_picture + 1) *
|
||||
(2 + 2 * ctx->num_planes +
|
||||
(mps * ctx->bits_per_mb) / 8)
|
||||
+ 200;
|
||||
|
||||
if (ctx->alpha_bits) {
|
||||
// The alpha plane is run-coded and might exceed the bit budget.
|
||||
ctx->frame_size_upper_bound += (ctx->pictures_per_frame *
|
||||
ctx->slices_per_picture + 1) *
|
||||
/* num pixels per slice */ (ctx->mbs_per_slice * 256 *
|
||||
/* bits per pixel */ (1 + ctx->alpha_bits + 1) + 7 >> 3);
|
||||
}
|
||||
|
||||
avctx->codec_tag = ctx->profile_info->tag;
|
||||
avctx->profile = ctx->profile;
|
||||
|
||||
av_log(avctx, AV_LOG_DEBUG,
|
||||
"profile %d, %d slices, interlacing: %s, %d bits per MB\n",
|
||||
ctx->profile, ctx->slices_per_picture * ctx->pictures_per_frame,
|
||||
interlaced ? "yes" : "no", ctx->bits_per_mb);
|
||||
av_log(avctx, AV_LOG_DEBUG, "frame size upper bound: %d\n",
|
||||
ctx->frame_size_upper_bound);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t *ff_prores_kostya_write_frame_header(AVCodecContext *avctx, ProresContext *ctx,
|
||||
uint8_t **orig_buf, int flags,
|
||||
enum AVColorPrimaries color_primaries,
|
||||
enum AVColorTransferCharacteristic color_trc,
|
||||
enum AVColorSpace colorspace)
|
||||
{
|
||||
uint8_t *buf, *tmp;
|
||||
uint8_t frame_flags;
|
||||
|
||||
// frame atom
|
||||
*orig_buf += 4; // frame size
|
||||
bytestream_put_be32 (orig_buf, FRAME_ID); // frame container ID
|
||||
buf = *orig_buf;
|
||||
|
||||
// frame header
|
||||
tmp = buf;
|
||||
buf += 2; // frame header size will be stored here
|
||||
bytestream_put_be16 (&buf, ctx->chroma_factor != CFACTOR_Y422 || ctx->alpha_bits ? 1 : 0);
|
||||
bytestream_put_buffer(&buf, (uint8_t*)ctx->vendor, 4);
|
||||
bytestream_put_be16 (&buf, avctx->width);
|
||||
bytestream_put_be16 (&buf, avctx->height);
|
||||
|
||||
frame_flags = ctx->chroma_factor << 6;
|
||||
if (avctx->flags & AV_CODEC_FLAG_INTERLACED_DCT)
|
||||
frame_flags |= (flags & AV_FRAME_FLAG_TOP_FIELD_FIRST) ? 0x04 : 0x08;
|
||||
bytestream_put_byte (&buf, frame_flags);
|
||||
|
||||
bytestream_put_byte (&buf, 0); // reserved
|
||||
bytestream_put_byte (&buf, color_primaries);
|
||||
bytestream_put_byte (&buf, color_trc);
|
||||
bytestream_put_byte (&buf, colorspace);
|
||||
bytestream_put_byte (&buf, ctx->alpha_bits >> 3);
|
||||
bytestream_put_byte (&buf, 0); // reserved
|
||||
if (ctx->quant_sel != QUANT_MAT_DEFAULT) {
|
||||
bytestream_put_byte (&buf, 0x03); // matrix flags - both matrices are present
|
||||
bytestream_put_buffer(&buf, ctx->quant_mat, 64); // luma quantisation matrix
|
||||
bytestream_put_buffer(&buf, ctx->quant_chroma_mat, 64); // chroma quantisation matrix
|
||||
} else {
|
||||
bytestream_put_byte (&buf, 0x00); // matrix flags - default matrices are used
|
||||
}
|
||||
bytestream_put_be16 (&tmp, buf - *orig_buf); // write back frame header size
|
||||
return buf;
|
||||
}
|
||||
|
||||
uint8_t *ff_prores_kostya_write_picture_header(ProresContext *ctx, uint8_t *buf)
|
||||
{
|
||||
bytestream_put_byte (&buf, 0x40); // picture header size (in bits)
|
||||
buf += 4; // picture data size will be stored here
|
||||
bytestream_put_be16 (&buf, ctx->slices_per_picture);
|
||||
bytestream_put_byte (&buf, av_log2(ctx->mbs_per_slice) << 4); // slice width and height in MBs
|
||||
return buf;
|
||||
}
|
||||
137
libavcodec/proresenc_kostya_common.h
Normal file
137
libavcodec/proresenc_kostya_common.h
Normal file
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* Apple ProRes encoder
|
||||
*
|
||||
* Copyright (c) 2011 Anatoliy Wasserman
|
||||
* Copyright (c) 2012 Konstantin Shishkov
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#ifndef AVCODEC_PRORESENC_KOSTYA_COMMON_H
|
||||
#define AVCODEC_PRORESENC_KOSTYA_COMMON_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "libavutil/attributes_internal.h"
|
||||
#include "libavutil/log.h"
|
||||
#include "libavutil/mem_internal.h"
|
||||
#include "libavutil/pixfmt.h"
|
||||
#include "fdctdsp.h"
|
||||
|
||||
FF_VISIBILITY_PUSH_HIDDEN
|
||||
|
||||
#define CFACTOR_Y422 2
|
||||
#define CFACTOR_Y444 3
|
||||
|
||||
#define MAX_MBS_PER_SLICE 8
|
||||
|
||||
#define MAX_PLANES 4
|
||||
|
||||
#define NUM_MB_LIMITS 4
|
||||
|
||||
#define MAX_STORED_Q 16
|
||||
|
||||
enum {
|
||||
PRORES_PROFILE_AUTO = -1,
|
||||
PRORES_PROFILE_PROXY = 0,
|
||||
PRORES_PROFILE_LT,
|
||||
PRORES_PROFILE_STANDARD,
|
||||
PRORES_PROFILE_HQ,
|
||||
PRORES_PROFILE_4444,
|
||||
PRORES_PROFILE_4444XQ,
|
||||
};
|
||||
|
||||
enum {
|
||||
QUANT_MAT_PROXY = 0,
|
||||
QUANT_MAT_PROXY_CHROMA,
|
||||
QUANT_MAT_LT,
|
||||
QUANT_MAT_STANDARD,
|
||||
QUANT_MAT_HQ,
|
||||
QUANT_MAT_XQ_LUMA,
|
||||
QUANT_MAT_DEFAULT,
|
||||
};
|
||||
|
||||
struct AVCodecContext;
|
||||
struct AVFrame;
|
||||
|
||||
typedef struct prores_profile {
|
||||
const char *full_name;
|
||||
uint32_t tag;
|
||||
int min_quant;
|
||||
int max_quant;
|
||||
int br_tab[NUM_MB_LIMITS];
|
||||
int quant;
|
||||
int quant_chroma;
|
||||
} prores_profile;
|
||||
|
||||
typedef struct ProresContext {
|
||||
AVClass *class;
|
||||
DECLARE_ALIGNED(16, int16_t, blocks)[MAX_PLANES][64 * 4 * MAX_MBS_PER_SLICE];
|
||||
DECLARE_ALIGNED(16, uint16_t, emu_buf)[16*16];
|
||||
int16_t quants[MAX_STORED_Q][64];
|
||||
int16_t quants_chroma[MAX_STORED_Q][64];
|
||||
int16_t custom_q[64];
|
||||
int16_t custom_chroma_q[64];
|
||||
const uint8_t *quant_mat;
|
||||
const uint8_t *quant_chroma_mat;
|
||||
const uint8_t *scantable;
|
||||
|
||||
void (*fdct)(FDCTDSPContext *fdsp, const uint16_t *src,
|
||||
ptrdiff_t linesize, int16_t *block);
|
||||
FDCTDSPContext fdsp;
|
||||
|
||||
const struct AVFrame *pic;
|
||||
int mb_width, mb_height;
|
||||
int mbs_per_slice;
|
||||
int num_chroma_blocks, chroma_factor;
|
||||
int slices_width;
|
||||
int slices_per_picture;
|
||||
int pictures_per_frame; // 1 for progressive, 2 for interlaced
|
||||
int cur_picture_idx;
|
||||
int num_planes;
|
||||
int bits_per_mb;
|
||||
int force_quant;
|
||||
int alpha_bits;
|
||||
int warn;
|
||||
|
||||
char *vendor;
|
||||
int quant_sel;
|
||||
|
||||
int frame_size_upper_bound;
|
||||
|
||||
int profile;
|
||||
const struct prores_profile *profile_info;
|
||||
|
||||
int *slice_q;
|
||||
|
||||
struct ProresThreadData *tdata;
|
||||
} ProresContext;
|
||||
|
||||
av_cold int ff_prores_kostya_encode_init(struct AVCodecContext *avctx, ProresContext *ctx,
|
||||
enum AVPixelFormat pixfmt);
|
||||
|
||||
uint8_t *ff_prores_kostya_write_frame_header(struct AVCodecContext *avctx, ProresContext *ctx,
|
||||
uint8_t **orig_buf, int flags,
|
||||
enum AVColorPrimaries color_primaries,
|
||||
enum AVColorTransferCharacteristic color_trc,
|
||||
enum AVColorSpace colorspace);
|
||||
|
||||
uint8_t *ff_prores_kostya_write_picture_header(ProresContext *ctx, uint8_t *buf);
|
||||
|
||||
FF_VISIBILITY_POP_HIDDEN
|
||||
|
||||
#endif // AVCODEC_PRORESENC_KOSTYA_COMMON_H
|
||||
Reference in New Issue
Block a user