[FFmpeg-cvslog] avcodec/mlpenc: fix encoding last samples when not within full interval
Paul B Mahol
git at videolan.org
Tue Aug 31 22:23:19 EEST 2021
ffmpeg | branch: master | Paul B Mahol <onemda at gmail.com> | Mon Aug 30 22:27:33 2021 +0200| [9f420163c6207b9c54badd30056974a6b3450bfd] | committer: Paul B Mahol
avcodec/mlpenc: fix encoding last samples when not within full interval
Also implement shorten_by in bitstream.
> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=9f420163c6207b9c54badd30056974a6b3450bfd
---
libavcodec/mlpenc.c | 84 ++++++++++++++++++++++++++++++-----------------------
1 file changed, 47 insertions(+), 37 deletions(-)
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_packet(avctx, avpkt, 87500 * avctx->channels)) < 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},
More information about the ffmpeg-cvslog
mailing list