]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/proresenc.c
timecode: support >24h timecode.
[ffmpeg] / libavcodec / proresenc.c
index 20ab4512add2fb8a60cd0d32ea41cbf611e3bcdf..09678a002f584395d27acdd08a438418c2e28ccb 100644 (file)
@@ -27,6 +27,7 @@
 
 #include "avcodec.h"
 #include "put_bits.h"
+#include "bytestream.h"
 #include "dsputil.h"
 
 #define DEFAULT_SLICE_MB_WIDTH 8
@@ -233,10 +234,10 @@ static void encode_ac_coeffs(AVCodecContext *avctx, PutBitContext *pb,
     int prev_run = 4;
     int prev_level = 2;
 
-    int run = 0, level, code;
-    for (int i = 1; i < 64; i++) {
+    int run = 0, level, code, i, j;
+    for (i = 1; i < 64; i++) {
         int indp = progressive_scan[i];
-        for (int j = 0; j < blocks_per_slice; j++) {
+        for (j = 0; j < blocks_per_slice; j++) {
             int val = QSCALE(qmat, indp, in[(j << 6) + indp]);
             if (val) {
                 encode_codeword(pb, run, run_to_cb[FFMIN(prev_run, 15)]);
@@ -440,21 +441,21 @@ static int prores_encode_picture(AVCodecContext *avctx, AVFrame *pic,
 {
     int mb_width = (avctx->width + 15) >> 4;
     int mb_height = (avctx->height + 15) >> 4;
-    int hdr_size, sl_size, *slice_sizes;
-    int sl, mb_y, sl_data_size, qp;
+    int hdr_size, sl_size, i;
+    int mb_y, sl_data_size, qp;
     int unsafe_bot, unsafe_right;
-    uint8_t *sl_data;
+    uint8_t *sl_data, *sl_data_sizes;
     int slice_per_line = 0, rem = mb_width;
 
-    for (int i = av_log2(DEFAULT_SLICE_MB_WIDTH); i >= 0; --i) {
+    for (i = av_log2(DEFAULT_SLICE_MB_WIDTH); i >= 0; --i) {
         slice_per_line += rem >> i;
         rem &= (1 << i) - 1;
     }
 
     qp = qp_start_table[avctx->profile];
-    slice_sizes = av_malloc(slice_per_line * mb_height * sizeof(int));
-    sl = 0; hdr_size = 8; sl_data_size = buf_size - hdr_size;
-    sl_data = buf + hdr_size + (slice_per_line * mb_height * 2);
+    hdr_size = 8; sl_data_size = buf_size - hdr_size;
+    sl_data_sizes = buf + hdr_size;
+    sl_data = sl_data_sizes + (slice_per_line * mb_height * 2);
     for (mb_y = 0; mb_y < mb_height; mb_y++) {
         int mb_x = 0;
         int slice_mb_count = DEFAULT_SLICE_MB_WIDTH;
@@ -468,7 +469,7 @@ static int prores_encode_picture(AVCodecContext *avctx, AVFrame *pic,
             sl_size = encode_slice(avctx, pic, mb_x, mb_y, slice_mb_count,
                     sl_data, sl_data_size, unsafe_bot || unsafe_right, &qp);
 
-            slice_sizes[sl++]  = sl_size;
+            bytestream_put_be16(&sl_data_sizes, sl_size);
             sl_data           += sl_size;
             sl_data_size      -= sl_size;
             mb_x              += slice_mb_count;
@@ -480,11 +481,6 @@ static int prores_encode_picture(AVCodecContext *avctx, AVFrame *pic,
     AV_WB16(buf + 5, slice_per_line * mb_height);
     buf[7] = av_log2(DEFAULT_SLICE_MB_WIDTH) << 4;
 
-    for (int i = 0; i < slice_per_line * mb_height; i++)
-        AV_WB16(buf + hdr_size + (i << 1), slice_sizes[i]);
-
-    av_free(slice_sizes);
-
     return sl_data - buf;
 }
 
@@ -497,31 +493,25 @@ static int prores_encode_frame(AVCodecContext *avctx, unsigned char *buf,
     int pic_size = prores_encode_picture(avctx, pic, buf + header_size + 8,
             buf_size - header_size - 8);
 
-    AV_WB32(buf, pic_size + 8 + header_size);
-    AV_WB8 (buf + 4, 'i');
-    AV_WB8 (buf + 5, 'c');
-    AV_WB8 (buf + 6, 'p');
-    AV_WB8 (buf + 7, 'f');
-
-    AV_WB16(buf + 8, header_size);
-    AV_WB16(buf + 10, 0);
-    AV_WB8 (buf + 12, 'f');
-    AV_WB8 (buf + 13, 'm');
-    AV_WB8 (buf + 14, 'p');
-    AV_WB8 (buf + 15, 'g');
-    AV_WB16(buf + 16, pic->width);
-    AV_WB16(buf + 18, pic->height);
-    buf[20] = 0x83; // {10}(422){00}{00}(frame){11}
-    buf[21] = 0;
-    buf[22] = 2;
-    buf[23] = 2;
-    buf[24] = 6;
-    buf[25] = 32;
-    buf[26] = 0;
-    buf[27] = 3;
-
-    memcpy(buf + 28, QMAT_LUMA[avctx->profile], 64);
-    memcpy(buf + 92, QMAT_CHROMA[avctx->profile], 64);
+    bytestream_put_be32(&buf, pic_size + 8 + header_size);
+    bytestream_put_buffer(&buf, "icpf", 4);
+
+    bytestream_put_be16(&buf, header_size);
+    bytestream_put_be16(&buf, 0);
+    bytestream_put_buffer(&buf, "fmpg", 4);
+    bytestream_put_be16(&buf, avctx->width);
+    bytestream_put_be16(&buf, avctx->height);
+    *buf++ = 0x83; // {10}(422){00}{00}(frame){11}
+    *buf++ = 0;
+    *buf++ = 2;
+    *buf++ = 2;
+    *buf++ = 6;
+    *buf++ = 32;
+    *buf++ = 0;
+    *buf++ = 3;
+
+    bytestream_put_buffer(&buf, QMAT_LUMA[avctx->profile],   64);
+    bytestream_put_buffer(&buf, QMAT_CHROMA[avctx->profile], 64);
 
     return pic_size + 8 + header_size;
 }
@@ -538,7 +528,7 @@ static av_cold int prores_encode_init(AVCodecContext *avctx)
     int i;
     ProresContext* ctx = avctx->priv_data;
 
-    if (avctx->pix_fmt != PIX_FMT_YUV422P10LE) {
+    if (avctx->pix_fmt != PIX_FMT_YUV422P10) {
         av_log(avctx, AV_LOG_ERROR, "need YUV422P10\n");
         return -1;
     }
@@ -549,9 +539,11 @@ static av_cold int prores_encode_init(AVCodecContext *avctx)
     }
 
     if ((avctx->height & 0xf) || (avctx->width & 0xf)) {
-        ctx->fill_y = av_malloc(DEFAULT_SLICE_MB_WIDTH << 9);
-        ctx->fill_u = av_malloc(DEFAULT_SLICE_MB_WIDTH << 8);
-        ctx->fill_v = av_malloc(DEFAULT_SLICE_MB_WIDTH << 8);
+        ctx->fill_y = av_malloc(4 * (DEFAULT_SLICE_MB_WIDTH << 8));
+        if (!ctx->fill_y)
+            return AVERROR(ENOMEM);
+        ctx->fill_u = ctx->fill_y + (DEFAULT_SLICE_MB_WIDTH << 9);
+        ctx->fill_v = ctx->fill_u + (DEFAULT_SLICE_MB_WIDTH << 8);
     }
 
     if (avctx->profile == FF_PROFILE_UNKNOWN) {
@@ -587,9 +579,7 @@ static av_cold int prores_encode_close(AVCodecContext *avctx)
 {
     ProresContext* ctx = avctx->priv_data;
     av_freep(&avctx->coded_frame);
-    av_free(ctx->fill_y);
-    av_free(ctx->fill_u);
-    av_free(ctx->fill_v);
+    av_freep(&ctx->fill_y);
 
     return 0;
 }
@@ -602,8 +592,7 @@ AVCodec ff_prores_encoder = {
     .init           = prores_encode_init,
     .close          = prores_encode_close,
     .encode         = prores_encode_frame,
-    .pix_fmts       = (const enum PixelFormat[]){PIX_FMT_YUV422P10LE, PIX_FMT_NONE},
+    .pix_fmts       = (const enum PixelFormat[]){PIX_FMT_YUV422P10, PIX_FMT_NONE},
     .long_name      = NULL_IF_CONFIG_SMALL("Apple ProRes"),
-    .capabilities   = 0,
     .profiles       = profiles
 };