From b586a366ea5422580761b700e5458638eba97a13 Mon Sep 17 00:00:00 2001
From: Andrew Randrianasulu <randrianasulu@gmail.com>
Date: Fri, 10 Dec 2021 17:26:40 +0300
Subject: [PATCH 04/15] Improve truehd decoder/encoder from ffmpeg.git

---
 .../thirdparty/src/ffmpeg-4.4.patch_5         | 180 ++++++++++++++++++
 .../thirdparty/src/ffmpeg-4.4.patch_6         |  24 +++
 .../thirdparty/src/ffmpeg-4.4.patch_7         |  41 ++++
 .../thirdparty/src/ffmpeg-4.4.patch_8         |  43 +++++
 4 files changed, 288 insertions(+)
 create mode 100644 cinelerra-5.1/thirdparty/src/ffmpeg-4.4.patch_5
 create mode 100644 cinelerra-5.1/thirdparty/src/ffmpeg-4.4.patch_6
 create mode 100644 cinelerra-5.1/thirdparty/src/ffmpeg-4.4.patch_7
 create mode 100644 cinelerra-5.1/thirdparty/src/ffmpeg-4.4.patch_8

diff --git a/cinelerra-5.1/thirdparty/src/ffmpeg-4.4.patch_5 b/cinelerra-5.1/thirdparty/src/ffmpeg-4.4.patch_5
new file mode 100644
index 00000000..126e51e6
--- /dev/null
+++ b/cinelerra-5.1/thirdparty/src/ffmpeg-4.4.patch_5
@@ -0,0 +1,180 @@
+X-Git-Url: http://git.ffmpeg.org/gitweb/ffmpeg.git/blobdiff_plain/fea4f953b5c6e04b84ce9c11664c9cbcac171a60..9f420163c6207b9c54badd30056974a6b3450bfd:/libavcodec/mlpenc.c
+
+diff --git a/libavcodec/mlpenc.c b/libavcodec/mlpenc.c
+index 8b61fc6b1e..37052d9e38 100644
+--- a/libavcodec/mlpenc.c
++++ b/libavcodec/mlpenc.c
+@@ -103,7 +103,7 @@ typedef struct BestOffset {
+ /** Number of possible codebooks (counting "no codebooks") */
+ #define NUM_CODEBOOKS       4
+
+-typedef struct {
++typedef struct MLPEncodeContext {
+     AVCodecContext *avctx;
+
+     int             num_substreams;         ///< Number of substreams contained within this stream.
+@@ -129,7 +129,8 @@ typedef struct {
+     int32_t        *write_buffer;           ///< Pointer to data currently being written to bitstream.
+     int32_t        *sample_buffer;          ///< Pointer to current access unit samples.
+     int32_t        *major_scratch_buffer;   ///< Scratch buffer big enough to fit all data for one entire major frame interval.
+-    int32_t        *last_frame;             ///< Pointer to last frame with data to encode.
++    int32_t        last_frames;             ///< Signal last frames.
++    int32_t        last_index;
+
+     int32_t        *lpc_sample_buffer;
+
+@@ -201,6 +202,10 @@ typedef struct {
+
+     unsigned int    max_codebook_search;
+
++    int             shorten_by;
++
++    int64_t         pts;
++
+     LPCContext      lpc_ctx;
+ } MLPEncodeContext;
+
+@@ -1116,9 +1121,13 @@ static uint8_t *write_substrs(MLPEncodeContext *ctx, uint8_t *buf, int buf_size,
+
+         rh->lossless_check_data ^= *lossless_check_data++;
+
+-        if (ctx->last_frame == ctx->inout_buffer) {
+-            /* TODO find a sample and implement shorten_by. */
+-            put_bits(&pb, 32, END_OF_STREAM);
++        if (ctx->last_frames == 0 && ctx->shorten_by) {
++            if (ctx->avctx->codec_id == AV_CODEC_ID_TRUEHD) {
++                put_bits(&pb, 16, END_OF_STREAM & 0xFFFF);
++                put_bits(&pb, 16, (ctx->shorten_by & 0x1FFF) | 0x2000);
++            } else {
++                put_bits(&pb, 32, END_OF_STREAM);
++            }
+         }
+
+         /* Data must be flushed for the checksum and parity to be correct;
+@@ -2216,42 +2225,35 @@ static int mlp_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
+     int restart_frame, ret;
+     uint8_t *data;
+
++    if (!frame && !ctx->last_frames--)
++        return 0;
++
+     if ((ret = ff_alloc_packet2(avctx, avpkt, 87500 * avctx->channels, 0)) < 0)
+         return ret;
+
+-    /* add current frame to queue */
+-    if ((ret = ff_af_queue_add(&ctx->afq, frame)) < 0)
+-        return ret;
++    if (frame) {
++        /* add current frame to queue */
++        if ((ret = ff_af_queue_add(&ctx->afq, frame)) < 0)
++            return ret;
++        ctx->last_frames = ctx->max_restart_interval;
++        ctx->last_index = ctx->frame_index;
++    }
+
+-    data = frame->data[0];
++    data = frame ? frame->data[0] : NULL;
+
+     ctx->frame_index = avctx->frame_number % ctx->max_restart_interval;
+
+     ctx->inout_buffer = ctx->major_inout_buffer
+                       + ctx->frame_index * ctx->one_sample_buffer_size;
+
+-    if (ctx->last_frame == ctx->inout_buffer) {
+-        return 0;
+-    }
+-
+     ctx->sample_buffer = ctx->major_scratch_buffer
+                        + ctx->frame_index * ctx->one_sample_buffer_size;
+
+     ctx->write_buffer = ctx->inout_buffer;
+
+     if (avctx->frame_number < ctx->max_restart_interval) {
+-        if (data) {
++        if (data)
+             goto input_and_return;
+-        } else {
+-            /* There are less frames than the requested major header interval.
+-             * Update the context to reflect this.
+-             */
+-            ctx->max_restart_interval = avctx->frame_number;
+-            ctx->frame_index = 0;
+-
+-            ctx->sample_buffer = ctx->major_scratch_buffer;
+-            ctx->inout_buffer = ctx->major_inout_buffer;
+-        }
+     }
+
+     if (ctx->frame_size[ctx->frame_index] > MAX_BLOCKSIZE) {
+@@ -2278,14 +2280,13 @@ static int mlp_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
+
+ input_and_return:
+
+-    if (data) {
+-        ctx->frame_size[ctx->frame_index] = avctx->frame_size;
+-        ctx->next_major_frame_size += avctx->frame_size;
+-        ctx->next_major_number_of_frames++;
++    if (frame)
++        ctx->shorten_by = avctx->frame_size - frame->nb_samples;
++    ctx->frame_size[ctx->frame_index] = avctx->frame_size;
++    ctx->next_major_frame_size += avctx->frame_size;
++    ctx->next_major_number_of_frames++;
++    if (data)
+         input_data(ctx, data);
+-    } else if (!ctx->last_frame) {
+-        ctx->last_frame = ctx->inout_buffer;
+-    }
+
+     restart_frame = (ctx->frame_index + 1) % ctx->min_restart_interval;
+
+@@ -2315,10 +2316,11 @@ input_and_return:
+                                        (ctx->frame_index / ctx->min_restart_interval)*(ctx->sequence_size)*(ctx->num_substreams) +
+                                        (ctx->seq_offset[seq_index])*(ctx->num_substreams);
+
+-            for (index = 0; index < ctx->number_of_frames; index++) {
++            for (index = 0; index < ctx->number_of_frames; index++)
+                 number_of_samples += ctx->frame_size[(ctx->starting_frame_index + index) % ctx->max_restart_interval];
+-            }
+             ctx->number_of_samples = number_of_samples;
++            if (!ctx->number_of_samples)
++                break;
+
+             for (index = 0; index < ctx->seq_size[seq_index]; index++) {
+                 clear_channel_params(ctx->seq_channel_params + index * ctx->avctx->channels, ctx->avctx->channels);
+@@ -2343,8 +2345,16 @@ input_and_return:
+
+ no_data_left:
+
+-    ff_af_queue_remove(&ctx->afq, avctx->frame_size, &avpkt->pts,
+-                       &avpkt->duration);
++    if (ctx->afq.frame_count > 0) {
++        ff_af_queue_remove(&ctx->afq, avctx->frame_size, &avpkt->pts,
++                           &avpkt->duration);
++        ctx->pts = avpkt->pts + avpkt->duration;
++    } else {
++        avpkt->pts = ctx->pts;
++        ctx->pts += avctx->frame_size;
++    }
++    if (!frame)
++        avctx->frame_number++;
+     avpkt->size = bytes_written;
+     *got_packet = 1;
+     return 0;
+@@ -2379,7 +2389,7 @@ const AVCodec ff_mlp_encoder = {
+     .init                   = mlp_encode_init,
+     .encode2                = mlp_encode_frame,
+     .close                  = mlp_encode_close,
+-    .capabilities           = AV_CODEC_CAP_SMALL_LAST_FRAME | AV_CODEC_CAP_EXPERIMENTAL,
++    .capabilities           = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_EXPERIMENTAL,
+     .sample_fmts            = (const enum AVSampleFormat[]) {AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE},
+     .supported_samplerates  = (const int[]) {44100, 48000, 88200, 96000, 176400, 192000, 0},
+     .channel_layouts        = ff_mlp_channel_layouts,
+@@ -2396,7 +2406,7 @@ const AVCodec ff_truehd_encoder = {
+     .init                   = mlp_encode_init,
+     .encode2                = mlp_encode_frame,
+     .close                  = mlp_encode_close,
+-    .capabilities           = AV_CODEC_CAP_SMALL_LAST_FRAME | AV_CODEC_CAP_EXPERIMENTAL,
++    .capabilities           = AV_CODEC_CAP_SMALL_LAST_FRAME | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_EXPERIMENTAL,
+     .sample_fmts            = (const enum AVSampleFormat[]) {AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE},
+     .supported_samplerates  = (const int[]) {44100, 48000, 88200, 96000, 176400, 192000, 0},
+     .channel_layouts        = (const uint64_t[]) {AV_CH_LAYOUT_STEREO, AV_CH_LAYOUT_5POINT0_BACK, AV_CH_LAYOUT_5POINT1_BACK, 0},
diff --git a/cinelerra-5.1/thirdparty/src/ffmpeg-4.4.patch_6 b/cinelerra-5.1/thirdparty/src/ffmpeg-4.4.patch_6
new file mode 100644
index 00000000..3c0b4352
--- /dev/null
+++ b/cinelerra-5.1/thirdparty/src/ffmpeg-4.4.patch_6
@@ -0,0 +1,24 @@
+X-Git-Url: http://git.ffmpeg.org/gitweb/ffmpeg.git/blobdiff_plain/61c2c9ef8e66920c8ba308e8fa9f36ae602f8245..2bb9d2be5e2e1d971e5b80358098f2a7fce06e0e:/libavcodec/mlpenc.c
+
+diff --git a/libavcodec/mlpenc.c b/libavcodec/mlpenc.c
+index 37052d9e38..443cb41cf5 100644
+--- a/libavcodec/mlpenc.c
++++ b/libavcodec/mlpenc.c
+@@ -2390,7 +2390,7 @@ const AVCodec ff_mlp_encoder = {
+     .encode2                = mlp_encode_frame,
+     .close                  = mlp_encode_close,
+     .capabilities           = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_EXPERIMENTAL,
+-    .sample_fmts            = (const enum AVSampleFormat[]) {AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE},
++    .sample_fmts            = (const enum AVSampleFormat[]) {AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_NONE},
+     .supported_samplerates  = (const int[]) {44100, 48000, 88200, 96000, 176400, 192000, 0},
+     .channel_layouts        = ff_mlp_channel_layouts,
+     .caps_internal          = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
+@@ -2407,7 +2407,7 @@ const AVCodec ff_truehd_encoder = {
+     .encode2                = mlp_encode_frame,
+     .close                  = mlp_encode_close,
+     .capabilities           = AV_CODEC_CAP_SMALL_LAST_FRAME | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_EXPERIMENTAL,
+-    .sample_fmts            = (const enum AVSampleFormat[]) {AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE},
++    .sample_fmts            = (const enum AVSampleFormat[]) {AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_NONE},
+     .supported_samplerates  = (const int[]) {44100, 48000, 88200, 96000, 176400, 192000, 0},
+     .channel_layouts        = (const uint64_t[]) {AV_CH_LAYOUT_STEREO, AV_CH_LAYOUT_5POINT0_BACK, AV_CH_LAYOUT_5POINT1_BACK, 0},
+     .caps_internal          = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
diff --git a/cinelerra-5.1/thirdparty/src/ffmpeg-4.4.patch_7 b/cinelerra-5.1/thirdparty/src/ffmpeg-4.4.patch_7
new file mode 100644
index 00000000..2203a3a9
--- /dev/null
+++ b/cinelerra-5.1/thirdparty/src/ffmpeg-4.4.patch_7
@@ -0,0 +1,41 @@
+X-Git-Url: http://git.ffmpeg.org/gitweb/ffmpeg.git/blobdiff_plain/a4c98c507ed3c729fc92d641b974385f8aa37b33..5673a4842556b79a92a1ede6e9696506fd4161ad:/libavcodec/mlpdec.c
+
+diff --git a/libavcodec/mlpdec.c b/libavcodec/mlpdec.c
+index e4992550ee..0fac5ad754 100644
+--- a/libavcodec/mlpdec.c
++++ b/libavcodec/mlpdec.c
+@@ -1330,6 +1330,18 @@ error:
+     return AVERROR_INVALIDDATA;
+ }
+
++static void mlp_decode_flush(AVCodecContext *avctx)
++{
++    MLPDecodeContext *m = avctx->priv_data;
++
++    m->params_valid = 0;
++    for (int substr = 0; substr <= m->max_decoded_substream; substr++){
++        SubStream *s = &m->substream[substr];
++
++        s->lossless_check_data = 0xffffffff;
++    }
++}
++
+ #if CONFIG_MLP_DECODER
+ const AVCodec ff_mlp_decoder = {
+     .name           = "mlp",
+@@ -1339,6 +1351,7 @@ const AVCodec ff_mlp_decoder = {
+     .priv_data_size = sizeof(MLPDecodeContext),
+     .init           = mlp_decode_init,
+     .decode         = read_access_unit,
++    .flush          = mlp_decode_flush,
+     .capabilities   = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF,
+     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
+ };
+@@ -1352,6 +1365,7 @@ const AVCodec ff_truehd_decoder = {
+     .priv_data_size = sizeof(MLPDecodeContext),
+     .init           = mlp_decode_init,
+     .decode         = read_access_unit,
++    .flush          = mlp_decode_flush,
+     .capabilities   = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF,
+     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
+ };
diff --git a/cinelerra-5.1/thirdparty/src/ffmpeg-4.4.patch_8 b/cinelerra-5.1/thirdparty/src/ffmpeg-4.4.patch_8
new file mode 100644
index 00000000..c59a5ee8
--- /dev/null
+++ b/cinelerra-5.1/thirdparty/src/ffmpeg-4.4.patch_8
@@ -0,0 +1,43 @@
+X-Git-Url: http://git.ffmpeg.org/gitweb/ffmpeg.git/blobdiff_plain/9f420163c6207b9c54badd30056974a6b3450bfd..034133a0df5f327aba36ee25db9452cda9e1a62b:/libavcodec/mlpdec.c
+
+diff --git a/libavcodec/mlpdec.c b/libavcodec/mlpdec.c
+index 0fac5ad754..08db5dc63c 100644
+--- a/libavcodec/mlpdec.c
++++ b/libavcodec/mlpdec.c
+@@ -53,6 +53,8 @@
+ typedef struct SubStream {
+     /// Set if a valid restart header has been read. Otherwise the substream cannot be decoded.
+     uint8_t     restart_seen;
++    /// Set if end of stream is encountered
++    uint8_t     end_of_stream;
+
+     //@{
+     /** restart header data */
+@@ -1286,8 +1288,8 @@ static int read_access_unit(AVCodecContext *avctx, void* data,
+             else if (m->avctx->codec_id == AV_CODEC_ID_MLP    && shorten_by != 0xD234)
+                 return AVERROR_INVALIDDATA;
+
+-            if (substr == m->max_decoded_substream)
+-                av_log(m->avctx, AV_LOG_INFO, "End of stream indicated.\n");
++            av_log(m->avctx, AV_LOG_DEBUG, "End of stream indicated.\n");
++            s->end_of_stream = 1;
+         }
+
+         if (substream_parity_present[substr]) {
+@@ -1319,6 +1321,16 @@ next_substr:
+     if ((ret = output_data(m, m->max_decoded_substream, data, got_frame_ptr)) < 0)
+         return ret;
+
++    for (substr = 0; substr <= m->max_decoded_substream; substr++){
++        SubStream *s = &m->substream[substr];
++
++        if (s->end_of_stream) {
++            s->lossless_check_data = 0xffffffff;
++            s->end_of_stream = 0;
++            m->params_valid = 0;
++        }
++    }
++
+     return length;
+
+ substream_length_mismatch:
-- 
2.34.1

