*
* Copyright (c) 2012 Konstantin Shishkov
*
- * This file is part of Libav.
+ * This encoder appears to be based on Anatoliy Wassermans considering
+ * similarities in the bugs.
*
- * Libav is free software; you can redistribute it and/or
+ * 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.
*
- * Libav is distributed in the hope that it will be useful,
+ * 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 Libav; if not, write to the Free Software
+ * License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#define MAX_PLANES 4
enum {
+ PRORES_PROFILE_AUTO = -1,
PRORES_PROFILE_PROXY = 0,
PRORES_PROFILE_LT,
PRORES_PROFILE_STANDARD,
static void put_alpha_diff(PutBitContext *pb, int cur, int prev, int abits)
{
- const int mask = (1 << abits) - 1;
const int dbits = (abits == 8) ? 4 : 7;
const int dsize = 1 << dbits - 1;
int diff = cur - prev;
- diff &= mask;
+ diff = av_mod_uintp2(diff, abits);
if (diff >= (1 << abits) - dsize)
diff -= 1 << abits;
if (diff < -dsize || diff > dsize || !diff) {
static int est_alpha_diff(int cur, int prev, int abits)
{
- const int mask = (1 << abits) - 1;
const int dbits = (abits == 8) ? 4 : 7;
const int dsize = 1 << dbits - 1;
int diff = cur - prev;
- diff &= mask;
+ diff = av_mod_uintp2(diff, abits);
if (diff >= (1 << abits) - dsize)
diff -= 1 << abits;
if (diff < -dsize || diff > dsize || !diff)
int sizes[4] = { 0 };
int slice_hdr_size = 2 + 2 * (ctx->num_planes - 1);
int frame_size, picture_size, slice_size;
- int pkt_size, ret, max_slice_size = 0;
+ int pkt_size, ret;
+ int max_slice_size = (ctx->frame_size_upper_bound - 200) / (ctx->pictures_per_frame * ctx->slices_per_picture + 1);
uint8_t frame_flags;
ctx->pic = pic;
-#if FF_API_CODED_FRAME
-FF_DISABLE_DEPRECATION_WARNINGS
- avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I;
- avctx->coded_frame->key_frame = 1;
-FF_ENABLE_DEPRECATION_WARNINGS
-#endif
-
pkt_size = ctx->frame_size_upper_bound;
- if ((ret = ff_alloc_packet(pkt, pkt_size + FF_MIN_BUFFER_SIZE)) < 0) {
- av_log(avctx, AV_LOG_ERROR, "Error getting output packet.\n");
+ if ((ret = ff_alloc_packet2(avctx, pkt, pkt_size + FF_MIN_BUFFER_SIZE, 0)) < 0)
return ret;
- }
orig_buf = pkt->data;
// slices
if (!ctx->force_quant) {
- ret = avctx->execute2(avctx, find_quant_thread, NULL, NULL,
+ ret = avctx->execute2(avctx, find_quant_thread, (void*)pic, NULL,
ctx->mb_height);
if (ret)
return ret;
uint8_t *start = pkt->data;
// Recompute new size according to max_slice_size
// and deduce delta
- int delta = 200 + ctx->pictures_per_frame *
- ctx->slices_per_picture * max_slice_size -
- pkt_size;
+ int delta = 200 + (ctx->pictures_per_frame *
+ ctx->slices_per_picture + 1) *
+ max_slice_size - pkt_size;
delta = FFMAX(delta, 2 * max_slice_size);
ctx->frame_size_upper_bound += delta;
slice_hdr = pkt->data + (slice_hdr - start);
tmp = pkt->data + (tmp - start);
}
- init_put_bits(&pb, buf, (pkt_size - (buf - orig_buf)) * 8);
+ init_put_bits(&pb, buf, (pkt_size - (buf - orig_buf)));
ret = encode_slice(avctx, pic, &pb, sizes, x, y, q,
mbs_per_slice);
if (ret < 0)
}
}
- if (ctx->pictures_per_frame == 1)
- picture_size = buf - picture_size_pos - 6;
- else
- picture_size = buf - picture_size_pos + 1;
+ picture_size = buf - (picture_size_pos - 1);
bytestream_put_be32(&picture_size_pos, picture_size);
}
if (ctx->tdata) {
for (i = 0; i < avctx->thread_count; i++)
- av_free(ctx->tdata[i].nodes);
+ av_freep(&ctx->tdata[i].nodes);
}
av_freep(&ctx->tdata);
av_freep(&ctx->slice_q);
int interlaced = !!(avctx->flags & AV_CODEC_FLAG_INTERLACED_DCT);
avctx->bits_per_raw_sample = 10;
+#if FF_API_CODED_FRAME
+FF_DISABLE_DEPRECATION_WARNINGS
+ avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I;
+ avctx->coded_frame->key_frame = 1;
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
ctx->fdct = prores_fdct;
ctx->scantable = interlaced ? ff_prores_interlaced_scan
"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) {
+ // 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);
ctx->bits_per_mb += ls * 4;
}
- ctx->frame_size_upper_bound = ctx->pictures_per_frame *
- ctx->slices_per_picture *
+ 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 *
+ 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);
}
{ "mbs_per_slice", "macroblocks per slice", OFFSET(mbs_per_slice),
AV_OPT_TYPE_INT, { .i64 = 8 }, 1, MAX_MBS_PER_SLICE, VE },
{ "profile", NULL, OFFSET(profile), AV_OPT_TYPE_INT,
- { .i64 = PRORES_PROFILE_STANDARD },
- PRORES_PROFILE_PROXY, PRORES_PROFILE_4444, VE, "profile" },
+ { .i64 = PRORES_PROFILE_AUTO },
+ PRORES_PROFILE_AUTO, PRORES_PROFILE_4444, VE, "profile" },
+ { "auto", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = PRORES_PROFILE_AUTO },
+ 0, 0, VE, "profile" },
{ "proxy", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = PRORES_PROFILE_PROXY },
0, 0, VE, "profile" },
{ "lt", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = PRORES_PROFILE_LT },
.version = LIBAVUTIL_VERSION_INT,
};
-AVCodec ff_prores_encoder = {
- .name = "prores",
+AVCodec ff_prores_ks_encoder = {
+ .name = "prores_ks",
.long_name = NULL_IF_CONFIG_SMALL("Apple ProRes (iCodec Pro)"),
.type = AVMEDIA_TYPE_VIDEO,
.id = AV_CODEC_ID_PRORES,