diff options
author | Paul B Mahol <onemda@gmail.com> | 2021-08-30 23:27:33 +0300 |
---|---|---|
committer | Paul B Mahol <onemda@gmail.com> | 2021-08-31 22:22:02 +0300 |
commit | 9f420163c6207b9c54badd30056974a6b3450bfd (patch) | |
tree | 44ab605aefcc5b42cabccbfc42895ffe0676c337 /libavcodec | |
parent | fea4f953b5c6e04b84ce9c11664c9cbcac171a60 (diff) |
avcodec/mlpenc: fix encoding last samples when not within full interval
Also implement shorten_by in bitstream.
Diffstat (limited to 'libavcodec')
-rw-r--r-- | libavcodec/mlpenc.c | 84 |
1 files 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}, |