|
|
|
@ -249,7 +249,7 @@ typedef struct XMADecodeCtx { |
|
|
|
|
AVFrame *frames[XMA_MAX_STREAMS]; |
|
|
|
|
int current_stream; |
|
|
|
|
int num_streams; |
|
|
|
|
AVAudioFifo *samples[2][XMA_MAX_CHANNELS]; |
|
|
|
|
AVAudioFifo *samples[2][XMA_MAX_STREAMS]; |
|
|
|
|
int start_channel[XMA_MAX_STREAMS]; |
|
|
|
|
int trim_start, trim_end; |
|
|
|
|
} XMADecodeCtx; |
|
|
|
@ -1829,7 +1829,7 @@ static int xma_decode_packet(AVCodecContext *avctx, void *data, |
|
|
|
|
XMADecodeCtx *s = avctx->priv_data; |
|
|
|
|
int got_stream_frame_ptr = 0; |
|
|
|
|
AVFrame *frame = data; |
|
|
|
|
int i, ret, eof; |
|
|
|
|
int i, ret, eof = 1; |
|
|
|
|
|
|
|
|
|
if (!s->frames[s->current_stream]->data[0]) { |
|
|
|
|
avctx->internal->skip_samples = 64; |
|
|
|
@ -1846,22 +1846,21 @@ static int xma_decode_packet(AVCodecContext *avctx, void *data, |
|
|
|
|
/* decode current stream packet */ |
|
|
|
|
ret = decode_packet(avctx, &s->xma[s->current_stream], s->frames[s->current_stream], |
|
|
|
|
&got_stream_frame_ptr, avpkt); |
|
|
|
|
eof = s->xma[s->current_stream].eof_done; |
|
|
|
|
if (s->xma[s->current_stream].trim_start) |
|
|
|
|
s->trim_start = s->xma[s->current_stream].trim_start; |
|
|
|
|
if (s->xma[s->current_stream].trim_end) |
|
|
|
|
s->trim_end = s->xma[s->current_stream].trim_end; |
|
|
|
|
|
|
|
|
|
if (s->xma[0].trim_start) |
|
|
|
|
s->trim_start = s->xma[0].trim_start; |
|
|
|
|
if (s->xma[0].trim_end) |
|
|
|
|
s->trim_end = s->xma[0].trim_end; |
|
|
|
|
|
|
|
|
|
/* copy stream samples (1/2ch) to sample buffer (Nch) */ |
|
|
|
|
if (got_stream_frame_ptr) { |
|
|
|
|
int start_ch = s->start_channel[s->current_stream]; |
|
|
|
|
const int nb_samples = s->frames[s->current_stream]->nb_samples; |
|
|
|
|
void *left[1] = { s->frames[s->current_stream]->extended_data[0] }; |
|
|
|
|
void *right[1] = { s->frames[s->current_stream]->extended_data[1] }; |
|
|
|
|
|
|
|
|
|
av_audio_fifo_write(s->samples[0][start_ch + 0], left, nb_samples); |
|
|
|
|
av_audio_fifo_write(s->samples[0][s->current_stream], left, nb_samples); |
|
|
|
|
if (s->xma[s->current_stream].nb_channels > 1) |
|
|
|
|
av_audio_fifo_write(s->samples[1][start_ch + 1], right, nb_samples); |
|
|
|
|
av_audio_fifo_write(s->samples[1][s->current_stream], right, nb_samples); |
|
|
|
|
} else if (ret < 0) { |
|
|
|
|
s->current_stream = 0; |
|
|
|
|
return ret; |
|
|
|
@ -1892,37 +1891,33 @@ static int xma_decode_packet(AVCodecContext *avctx, void *data, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* all other streams skip next packet */ |
|
|
|
|
for (i = 0; i < s->num_streams; i++) |
|
|
|
|
s->xma[i].skip_packets = FFMAX(0, s->xma[i].skip_packets - 1); |
|
|
|
|
|
|
|
|
|
for (i = 0; i < s->num_streams; i++) { |
|
|
|
|
int start_ch = s->start_channel[s->current_stream]; |
|
|
|
|
|
|
|
|
|
nb_samples = FFMIN(nb_samples, av_audio_fifo_size(s->samples[0][start_ch])); |
|
|
|
|
eof &= s->xma[i].eof_done; |
|
|
|
|
s->xma[i].skip_packets = FFMAX(0, s->xma[i].skip_packets - 1); |
|
|
|
|
nb_samples = FFMIN(nb_samples, av_audio_fifo_size(s->samples[0][i])); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* copy samples from buffer to output if possible */ |
|
|
|
|
if (nb_samples > 4096 || eof) { |
|
|
|
|
if (nb_samples > 8192 || eof || !avpkt->size) { |
|
|
|
|
int bret; |
|
|
|
|
|
|
|
|
|
if (eof) { |
|
|
|
|
nb_samples -= FFMIN(nb_samples, s->trim_end + s->trim_start - 128 - 64); |
|
|
|
|
if (!avpkt->size) { |
|
|
|
|
nb_samples -= s->trim_end + s->trim_start - 128 - 64; |
|
|
|
|
s->trim_end = s->trim_start = 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
frame->nb_samples = nb_samples; |
|
|
|
|
if (frame->nb_samples <= 0) |
|
|
|
|
return ret; |
|
|
|
|
if ((bret = ff_get_buffer(avctx, frame, 0)) < 0) |
|
|
|
|
return bret; |
|
|
|
|
|
|
|
|
|
for (i = 0; i < s->num_streams; i++) { |
|
|
|
|
const int start_ch = s->start_channel[s->current_stream]; |
|
|
|
|
void *left[1] = { frame->extended_data[0] }; |
|
|
|
|
void *right[1] = { frame->extended_data[1] }; |
|
|
|
|
const int start_ch = s->start_channel[i]; |
|
|
|
|
void *left[1] = { frame->extended_data[start_ch + 0] }; |
|
|
|
|
void *right[1] = { frame->extended_data[start_ch + 1] }; |
|
|
|
|
|
|
|
|
|
av_audio_fifo_read(s->samples[0][start_ch + 0], left, nb_samples); |
|
|
|
|
if (s->xma[s->current_stream].nb_channels > 1) |
|
|
|
|
av_audio_fifo_read(s->samples[1][start_ch + 1], right, nb_samples); |
|
|
|
|
av_audio_fifo_read(s->samples[0][i], left, nb_samples); |
|
|
|
|
if (s->xma[i].nb_channels > 1) |
|
|
|
|
av_audio_fifo_read(s->samples[1][i], right, nb_samples); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
*got_frame_ptr = 1; |
|
|
|
@ -1986,7 +1981,7 @@ static av_cold int xma_decode_init(AVCodecContext *avctx) |
|
|
|
|
if (start_channels != avctx->channels) |
|
|
|
|
return AVERROR_INVALIDDATA; |
|
|
|
|
|
|
|
|
|
for (int i = 0; i < XMA_MAX_CHANNELS; i++) { |
|
|
|
|
for (int i = 0; i < XMA_MAX_STREAMS; i++) { |
|
|
|
|
s->samples[0][i] = av_audio_fifo_alloc(avctx->sample_fmt, 1, 64 * 512); |
|
|
|
|
s->samples[1][i] = av_audio_fifo_alloc(avctx->sample_fmt, 1, 64 * 512); |
|
|
|
|
if (!s->samples[0][i] || !s->samples[1][i]) |
|
|
|
@ -2007,7 +2002,7 @@ static av_cold int xma_decode_end(AVCodecContext *avctx) |
|
|
|
|
} |
|
|
|
|
s->num_streams = 0; |
|
|
|
|
|
|
|
|
|
for (i = 0; i < XMA_MAX_CHANNELS; i++) { |
|
|
|
|
for (i = 0; i < XMA_MAX_STREAMS; i++) { |
|
|
|
|
av_audio_fifo_free(s->samples[0][i]); |
|
|
|
|
av_audio_fifo_free(s->samples[1][i]); |
|
|
|
|
} |
|
|
|
@ -2045,7 +2040,7 @@ static void xma_flush(AVCodecContext *avctx) |
|
|
|
|
XMADecodeCtx *s = avctx->priv_data; |
|
|
|
|
int i; |
|
|
|
|
|
|
|
|
|
for (i = 0; i < XMA_MAX_CHANNELS; i++) { |
|
|
|
|
for (i = 0; i < XMA_MAX_STREAMS; i++) { |
|
|
|
|
av_audio_fifo_reset(s->samples[0][i]); |
|
|
|
|
av_audio_fifo_reset(s->samples[1][i]); |
|
|
|
|
} |
|
|
|
|