@@ -133,6 +133,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 */
@@ -124,6 +124,11 @@ static av_cold int wma_decode_init(AVCodecContext *avctx)
avctx->sample_fmt = AV_SAMPLE_FMT_FLTP;
+ /* Skip WMA encoder delay (>=32000: 4096, >=22050: 2048, >=8000: 1024).
+ * The amount doesn't seem specified in the flags or container (ASF/XWMA),
+ * but can be verified compared to Microsoft codecs' output. */
+ avctx->internal->skip_samples = s->frame_len * 2;
+
return 0;
}
@@ -819,7 +824,29 @@ static int wma_decode_superframe(AVCodecContext *avctx, void *data,
ff_tlog(avctx, "***decode_superframe:\n");
if (buf_size == 0) {
+ /* must output one final frame with remaining samples */
+
+ if (s->eof_done)
+ return 0;
+
+ /* get output buffer */
+ frame->nb_samples = s->frame_len;
+ if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
+ return ret;
+ samples = (float **) frame->extended_data;
+
+ /* clean output buffer and copy last IMCDT samples */
+ for (i = 0; i < s->avctx->channels; i++) {
+ memset(frame->extended_data[i], 0,
+ s->frame_len * sizeof(*s->frame_out[i]));
+
+ memcpy(frame->extended_data[i], &s->frame_out[i][0],
+ s->frame_len * sizeof(*s->frame_out[i]) >> 1);
+ }
+
s->last_superframe_len = 0;
+ s->eof_done = 1;
+ *got_frame_ptr = 1;
return 0;
}
if (buf_size < avctx->block_align) {
@@ -965,6 +992,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
@@ -978,7 +1008,7 @@ 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 },
};
@@ -994,7 +1024,7 @@ 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 },
};