avcodec/wmadec: fix WMA gapless playback

Fixes trac issue #7473.

Removes encoder delay (skip samples) and writes remaining frame samples after EOF to get correct sample count.

Output is now accurate vs players that use Microsoft's codecs (Windows Media Format Runtime).

Tested vs encode>decode WMAv2 with MS's codecs and most sample rate/bit rate/channel/mode combinations in ASF/XWMA.
WMAv1 appears to use the same delay, from FFmpeg samples.

Signed-off-by: bnnm <bananaman255@gmail.com>
This commit is contained in:
bnnm 2018-10-05 19:39:26 +02:00 committed by Paul B Mahol
parent d1971d69c7
commit 19802d170a
4 changed files with 27 additions and 8 deletions

View File

@ -135,6 +135,8 @@ typedef struct WMACodecContext {
float lsp_pow_m_table2[(1 << LSP_POW_BITS)];
AVFloatDSPContext *fdsp;
int eof_done; /* decode flag to output remaining samples after EOF */
#ifdef TRACE
int frame_count;
#endif /* TRACE */

View File

@ -135,6 +135,8 @@ static av_cold int wma_decode_init(AVCodecContext *avctx)
avctx->sample_fmt = AV_SAMPLE_FMT_FLTP;
avctx->internal->skip_samples = s->frame_len * 2;
return 0;
}
@ -829,7 +831,20 @@ static int wma_decode_superframe(AVCodecContext *avctx, void *data,
ff_tlog(avctx, "***decode_superframe:\n");
if (buf_size == 0) {
if (s->eof_done)
return 0;
frame->nb_samples = s->frame_len;
if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
return ret;
for (i = 0; i < s->avctx->channels; i++)
memcpy(frame->extended_data[i], &s->frame_out[i][0],
frame->nb_samples * sizeof(s->frame_out[i][0]));
s->last_superframe_len = 0;
s->eof_done = 1;
*got_frame_ptr = 1;
return 0;
}
if (buf_size < avctx->block_align) {
@ -975,6 +990,9 @@ static av_cold void flush(AVCodecContext *avctx)
s->last_bitoffset =
s->last_superframe_len = 0;
s->eof_done = 0;
avctx->internal->skip_samples = s->frame_len * 2;
}
#if CONFIG_WMAV1_DECODER
@ -988,7 +1006,7 @@ const AVCodec ff_wmav1_decoder = {
.close = ff_wma_end,
.decode = wma_decode_superframe,
.flush = flush,
.capabilities = AV_CODEC_CAP_DR1,
.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY,
.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP,
AV_SAMPLE_FMT_NONE },
.caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
@ -1005,7 +1023,7 @@ const AVCodec ff_wmav2_decoder = {
.close = ff_wma_end,
.decode = wma_decode_superframe,
.flush = flush,
.capabilities = AV_CODEC_CAP_DR1,
.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY,
.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP,
AV_SAMPLE_FMT_NONE },
.caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,

View File

@ -40,14 +40,14 @@ fate-wmavoice: $(FATE_WMAVOICE-yes)
FATE_WMA_ENCODE-$(call ENCDEC, WMAV1, ASF) += fate-wmav1-encode
fate-wmav1-encode: CMD = enc_dec_pcm asf wav s16le $(subst $(SAMPLES),$(TARGET_SAMPLES),$(REF)) -c:a wmav1 -b:a 128k
fate-wmav1-encode: CMP_SHIFT = -8192
fate-wmav1-encode: CMP_TARGET = 291.06
fate-wmav1-encode: CMP_SHIFT = 8192
fate-wmav1-encode: CMP_TARGET = 299.99
fate-wmav1-encode: SIZE_TOLERANCE = 4632
FATE_WMA_ENCODE-$(call ENCDEC, WMAV2, ASF) += fate-wmav2-encode
fate-wmav2-encode: CMD = enc_dec_pcm asf wav s16le $(subst $(SAMPLES),$(TARGET_SAMPLES),$(REF)) -c:a wmav2 -b:a 128k
fate-wmav2-encode: CMP_SHIFT = -8192
fate-wmav2-encode: CMP_TARGET = 258.32
fate-wmav2-encode: CMP_SHIFT = 8192
fate-wmav2-encode: CMP_TARGET = 267.92
fate-wmav2-encode: SIZE_TOLERANCE = 4632
$(FATE_WMA_ENCODE-yes): CMP = stddev

View File

@ -1,6 +1,4 @@
packet|codec_type=audio|stream_index=0|pts=0|pts_time=0.000000|dts=0|dts_time=0.000000|duration=22528|duration_time=0.510839|size=4092|pos=56|flags=K_
frame|media_type=audio|stream_index=0|key_frame=1|pts=0|pts_time=0.000000|pkt_dts=0|pkt_dts_time=0.000000|best_effort_timestamp=0|best_effort_timestamp_time=0.000000|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=56|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown
frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=56|pkt_size=3720|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown
frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=56|pkt_size=3348|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown
frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=56|pkt_size=2976|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown
frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=56|pkt_size=2604|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown
@ -191,3 +189,4 @@ frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N
frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=61436|pkt_size=744|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown
frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=61436|pkt_size=372|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown
packet|codec_type=audio|stream_index=0|pts=360448|pts_time=8.173424|dts=360448|dts_time=8.173424|duration=44|duration_time=0.000998|size=8|pos=65528|flags=K_
frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=N/A|pkt_duration_time=N/A|pkt_pos=N/A|pkt_size=0|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown