mirror of
https://github.com/LostArtefacts/TRX.git
synced 2025-04-28 20:58:07 +03:00
build: upgrade ffmpeg to 7.1
This commit is contained in:
parent
301fe93315
commit
63ce670d22
9 changed files with 188 additions and 143 deletions
|
@ -78,7 +78,7 @@ runs:
|
|||
# Install to separate staging paths for all architectures in
|
||||
# preparation for fusing universal libraries in a follow-up step.
|
||||
cd "$RUNNER_TEMP"
|
||||
git clone --depth 1 --branch "n4.4.1" https://github.com/FFmpeg/FFmpeg
|
||||
git clone --depth 1 --branch "n7.1" https://github.com/FFmpeg/FFmpeg
|
||||
cd FFmpeg
|
||||
|
||||
# Common FFmpeg configure options
|
||||
|
|
|
@ -171,12 +171,11 @@ static bool M_Convert(const int32_t sample_id)
|
|||
};
|
||||
|
||||
struct {
|
||||
int32_t src_format;
|
||||
int32_t src_channels;
|
||||
int32_t src_sample_rate;
|
||||
int32_t dst_format;
|
||||
int32_t dst_channels;
|
||||
int32_t dst_sample_rate;
|
||||
struct {
|
||||
int32_t format;
|
||||
AVChannelLayout ch_layout;
|
||||
int32_t sample_rate;
|
||||
} src, dst;
|
||||
SwrContext *ctx;
|
||||
} swr = {};
|
||||
|
||||
|
@ -279,17 +278,18 @@ static bool M_Convert(const int32_t sample_id)
|
|||
goto cleanup;
|
||||
}
|
||||
|
||||
if (!swr.ctx) {
|
||||
swr.src_sample_rate = av.codec_ctx->sample_rate;
|
||||
swr.src_channels = av.codec_ctx->channels;
|
||||
swr.src_format = av.codec_ctx->sample_fmt;
|
||||
swr.dst_sample_rate = AUDIO_WORKING_RATE;
|
||||
swr.dst_channels = 1;
|
||||
swr.dst_format = Audio_GetAVAudioFormat(AUDIO_WORKING_FORMAT);
|
||||
swr.ctx = swr_alloc_set_opts(
|
||||
swr.ctx, swr.dst_channels, swr.dst_format, swr.dst_sample_rate,
|
||||
swr.src_channels, swr.src_format, swr.src_sample_rate, 0, 0);
|
||||
if (!swr.ctx) {
|
||||
if (swr.ctx == nullptr) {
|
||||
swr.src.sample_rate = av.codec_ctx->sample_rate;
|
||||
swr.src.ch_layout = av.codec_ctx->ch_layout;
|
||||
swr.src.format = av.codec_ctx->sample_fmt;
|
||||
swr.dst.sample_rate = AUDIO_WORKING_RATE;
|
||||
av_channel_layout_default(&swr.dst.ch_layout, 1);
|
||||
swr.dst.format = Audio_GetAVAudioFormat(AUDIO_WORKING_FORMAT);
|
||||
swr_alloc_set_opts2(
|
||||
&swr.ctx, &swr.dst.ch_layout, swr.dst.format,
|
||||
swr.dst.sample_rate, &swr.src.ch_layout, swr.src.format,
|
||||
swr.src.sample_rate, 0, 0);
|
||||
if (swr.ctx == nullptr) {
|
||||
av_packet_unref(av.packet);
|
||||
error_code = AVERROR(ENOMEM);
|
||||
goto cleanup;
|
||||
|
@ -319,15 +319,15 @@ static bool M_Convert(const int32_t sample_id)
|
|||
const int32_t out_samples =
|
||||
swr_get_out_samples(swr.ctx, av.frame->nb_samples);
|
||||
av_samples_alloc(
|
||||
&out_buffer, nullptr, swr.dst_channels, out_samples,
|
||||
swr.dst_format, 1);
|
||||
&out_buffer, nullptr, swr.dst.ch_layout.nb_channels,
|
||||
out_samples, swr.dst.format, 1);
|
||||
int32_t resampled_size = swr_convert(
|
||||
swr.ctx, &out_buffer, out_samples,
|
||||
(const uint8_t **)av.frame->data, av.frame->nb_samples);
|
||||
while (resampled_size > 0) {
|
||||
int32_t out_buffer_size = av_samples_get_buffer_size(
|
||||
nullptr, swr.dst_channels, resampled_size, swr.dst_format,
|
||||
1);
|
||||
nullptr, swr.dst.ch_layout.nb_channels, resampled_size,
|
||||
swr.dst.format, 1);
|
||||
|
||||
if (out_buffer_size > 0) {
|
||||
working_buffer = Memory_Realloc(
|
||||
|
@ -351,10 +351,10 @@ static bool M_Convert(const int32_t sample_id)
|
|||
av_packet_unref(av.packet);
|
||||
}
|
||||
|
||||
int32_t sample_format_bytes = av_get_bytes_per_sample(swr.dst_format);
|
||||
sample->num_samples =
|
||||
working_buffer_size / sample_format_bytes / swr.dst_channels;
|
||||
sample->channels = swr.src_channels;
|
||||
int32_t sample_format_bytes = av_get_bytes_per_sample(swr.dst.format);
|
||||
sample->num_samples = working_buffer_size / sample_format_bytes
|
||||
/ swr.dst.ch_layout.nb_channels;
|
||||
sample->channels = swr.src.ch_layout.nb_channels;
|
||||
sample->sample_data = working_buffer;
|
||||
result = true;
|
||||
|
||||
|
@ -396,8 +396,7 @@ cleanup:
|
|||
}
|
||||
|
||||
if (av.codec_ctx) {
|
||||
avcodec_close(av.codec_ctx);
|
||||
av_freep(&av.codec_ctx);
|
||||
avcodec_free_context(&av.codec_ctx);
|
||||
}
|
||||
|
||||
if (av.format_ctx) {
|
||||
|
|
|
@ -52,12 +52,11 @@ typedef struct {
|
|||
} av;
|
||||
|
||||
struct {
|
||||
int32_t src_format;
|
||||
int32_t src_channels;
|
||||
int32_t src_sample_rate;
|
||||
int32_t dst_format;
|
||||
int32_t dst_channels;
|
||||
int32_t dst_sample_rate;
|
||||
struct {
|
||||
int32_t format;
|
||||
AVChannelLayout ch_layout;
|
||||
int32_t sample_rate;
|
||||
} src, dst;
|
||||
SwrContext *ctx;
|
||||
} swr;
|
||||
|
||||
|
@ -147,17 +146,18 @@ static bool M_EnqueueFrame(AUDIO_STREAM_SOUND *stream)
|
|||
int32_t error_code;
|
||||
|
||||
if (!stream->swr.ctx) {
|
||||
stream->swr.src_sample_rate = stream->av.codec_ctx->sample_rate;
|
||||
stream->swr.src_channels = stream->av.codec_ctx->channels;
|
||||
stream->swr.src_format = stream->av.codec_ctx->sample_fmt;
|
||||
stream->swr.dst_sample_rate = AUDIO_WORKING_RATE;
|
||||
stream->swr.dst_channels = AUDIO_WORKING_CHANNELS;
|
||||
stream->swr.dst_format = Audio_GetAVAudioFormat(AUDIO_WORKING_FORMAT);
|
||||
stream->swr.ctx = swr_alloc_set_opts(
|
||||
stream->swr.ctx, Audio_GetAVChannelLayout(stream->swr.dst_channels),
|
||||
stream->swr.dst_format, stream->swr.dst_sample_rate,
|
||||
Audio_GetAVChannelLayout(stream->swr.src_channels),
|
||||
stream->swr.src_format, stream->swr.src_sample_rate, 0, 0);
|
||||
stream->swr.src.sample_rate = stream->av.codec_ctx->sample_rate;
|
||||
stream->swr.src.ch_layout = stream->av.codec_ctx->ch_layout;
|
||||
stream->swr.src.format = stream->av.codec_ctx->sample_fmt;
|
||||
stream->swr.dst.sample_rate = AUDIO_WORKING_RATE;
|
||||
av_channel_layout_default(
|
||||
&stream->swr.dst.ch_layout, AUDIO_WORKING_CHANNELS);
|
||||
stream->swr.dst.format = Audio_GetAVAudioFormat(AUDIO_WORKING_FORMAT);
|
||||
swr_alloc_set_opts2(
|
||||
&stream->swr.ctx, &stream->swr.dst.ch_layout,
|
||||
stream->swr.dst.format, stream->swr.dst.sample_rate,
|
||||
&stream->swr.src.ch_layout, stream->swr.src.format,
|
||||
stream->swr.src.sample_rate, 0, 0);
|
||||
if (!stream->swr.ctx) {
|
||||
av_packet_unref(stream->av.packet);
|
||||
error_code = AVERROR(ENOMEM);
|
||||
|
@ -189,8 +189,8 @@ static bool M_EnqueueFrame(AUDIO_STREAM_SOUND *stream)
|
|||
const int32_t out_samples =
|
||||
swr_get_out_samples(stream->swr.ctx, stream->av.frame->nb_samples);
|
||||
av_samples_alloc(
|
||||
&out_buffer, nullptr, stream->swr.dst_channels, out_samples,
|
||||
stream->swr.dst_format, 1);
|
||||
&out_buffer, nullptr, stream->swr.dst.ch_layout.nb_channels,
|
||||
out_samples, stream->swr.dst.format, 1);
|
||||
int32_t resampled_size = swr_convert(
|
||||
stream->swr.ctx, &out_buffer, out_samples,
|
||||
(const uint8_t **)stream->av.frame->data,
|
||||
|
@ -199,8 +199,8 @@ static bool M_EnqueueFrame(AUDIO_STREAM_SOUND *stream)
|
|||
size_t out_pos = 0;
|
||||
while (resampled_size > 0) {
|
||||
const size_t out_buffer_size = av_samples_get_buffer_size(
|
||||
nullptr, stream->swr.dst_channels, resampled_size,
|
||||
stream->swr.dst_format, 1);
|
||||
nullptr, stream->swr.dst.ch_layout.nb_channels, resampled_size,
|
||||
stream->swr.dst.format, 1);
|
||||
|
||||
if (out_pos + out_buffer_size > m_DecodeBufferCapacity) {
|
||||
m_DecodeBufferCapacity = out_pos + out_buffer_size;
|
||||
|
@ -322,8 +322,8 @@ static bool M_InitialiseFromPath(int32_t sound_id, const char *file_path)
|
|||
|
||||
M_DecodeFrame(stream);
|
||||
|
||||
int32_t sdl_sample_rate = stream->av.codec_ctx->sample_rate;
|
||||
int32_t sdl_channels = stream->av.codec_ctx->channels;
|
||||
const int32_t sdl_sample_rate = stream->av.codec_ctx->sample_rate;
|
||||
const int32_t sdl_channels = stream->av.codec_ctx->ch_layout.nb_channels;
|
||||
|
||||
stream->is_read_done = false;
|
||||
stream->is_used = true;
|
||||
|
@ -474,14 +474,12 @@ bool Audio_Stream_Close(int32_t sound_id)
|
|||
AUDIO_STREAM_SOUND *stream = &m_Streams[sound_id];
|
||||
|
||||
if (stream->av.codec_ctx) {
|
||||
avcodec_close(stream->av.codec_ctx);
|
||||
|
||||
// XXX: potential libav bug - avcodec_close should free this info
|
||||
if (stream->av.codec_ctx->extradata != nullptr) {
|
||||
av_freep(&stream->av.codec_ctx->extradata);
|
||||
}
|
||||
|
||||
av_free(stream->av.codec_ctx);
|
||||
avcodec_free_context(&stream->av.codec_ctx);
|
||||
stream->av.codec_ctx = nullptr;
|
||||
}
|
||||
|
||||
|
@ -613,13 +611,15 @@ void Audio_Stream_Mix(float *dst_buffer, size_t len)
|
|||
const float *src_ptr = &m_MixBuffer[0];
|
||||
float *dst_ptr = dst_buffer;
|
||||
|
||||
if (stream->av.codec_ctx->channels == AUDIO_WORKING_CHANNELS) {
|
||||
const int32_t channels =
|
||||
stream->av.codec_ctx->ch_layout.nb_channels;
|
||||
if (channels == AUDIO_WORKING_CHANNELS) {
|
||||
for (int32_t s = 0; s < samples_gotten; s++) {
|
||||
for (int32_t c = 0; c < AUDIO_WORKING_CHANNELS; c++) {
|
||||
*dst_ptr++ += *src_ptr++ * stream->volume;
|
||||
}
|
||||
}
|
||||
} else if (stream->av.codec_ctx->channels == 1) {
|
||||
} else if (channels == 1) {
|
||||
for (int32_t s = 0; s < samples_gotten; s++) {
|
||||
for (int32_t c = 0; c < AUDIO_WORKING_CHANNELS; c++) {
|
||||
*dst_ptr++ += *src_ptr * stream->volume;
|
||||
|
@ -630,11 +630,10 @@ void Audio_Stream_Mix(float *dst_buffer, size_t len)
|
|||
for (int32_t s = 0; s < samples_gotten; s++) {
|
||||
// downmix to mono
|
||||
float src_sample = 0.0f;
|
||||
for (int32_t i = 0; i < stream->av.codec_ctx->channels;
|
||||
i++) {
|
||||
for (int32_t i = 0; i < channels; i++) {
|
||||
src_sample += *src_ptr++;
|
||||
}
|
||||
src_sample /= (float)stream->av.codec_ctx->channels;
|
||||
src_sample /= (float)channels;
|
||||
for (int32_t c = 0; c < AUDIO_WORKING_CHANNELS; c++) {
|
||||
*dst_ptr++ += src_sample * stream->volume;
|
||||
}
|
||||
|
|
|
@ -77,6 +77,9 @@ static bool M_Init(const char *const path, IMAGE_READER_CONTEXT *const ctx)
|
|||
AVStream *video_stream = nullptr;
|
||||
for (unsigned int i = 0; i < ctx->format_ctx->nb_streams; i++) {
|
||||
AVStream *current_stream = ctx->format_ctx->streams[i];
|
||||
if (current_stream->codecpar == nullptr) {
|
||||
continue;
|
||||
}
|
||||
if (current_stream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
|
||||
video_stream = current_stream;
|
||||
break;
|
||||
|
@ -165,9 +168,7 @@ static void M_Free(IMAGE_READER_CONTEXT *const ctx)
|
|||
}
|
||||
|
||||
if (ctx->codec_ctx != nullptr) {
|
||||
avcodec_close(ctx->codec_ctx);
|
||||
av_free(ctx->codec_ctx);
|
||||
ctx->codec_ctx = nullptr;
|
||||
avcodec_free_context(&ctx->codec_ctx);
|
||||
}
|
||||
|
||||
if (ctx->format_ctx != nullptr) {
|
||||
|
@ -490,9 +491,7 @@ cleanup:
|
|||
}
|
||||
|
||||
if (codec) {
|
||||
avcodec_close(codec_ctx);
|
||||
av_free(codec_ctx);
|
||||
codec_ctx = nullptr;
|
||||
avcodec_free_context(&codec_ctx);
|
||||
}
|
||||
|
||||
if (frame) {
|
||||
|
|
|
@ -90,7 +90,7 @@ typedef struct {
|
|||
} M_PACKET_LIST;
|
||||
|
||||
typedef struct {
|
||||
AVFifoBuffer *pkt_list;
|
||||
AVFifo *pkt_list;
|
||||
int nb_packets;
|
||||
int size;
|
||||
int64_t duration;
|
||||
|
@ -103,7 +103,7 @@ typedef struct {
|
|||
typedef struct {
|
||||
int freq;
|
||||
int channels;
|
||||
int64_t channel_layout;
|
||||
AVChannelLayout ch_layout;
|
||||
enum AVSampleFormat fmt;
|
||||
int frame_size;
|
||||
int bytes_per_sec;
|
||||
|
@ -131,6 +131,10 @@ typedef struct {
|
|||
AVRational sar;
|
||||
} M_FRAME;
|
||||
|
||||
typedef struct {
|
||||
int64_t pkt_pos;
|
||||
} M_FRAME_DATA;
|
||||
|
||||
typedef struct {
|
||||
M_FRAME queue[FRAME_QUEUE_SIZE];
|
||||
int rindex;
|
||||
|
@ -223,6 +227,7 @@ typedef struct {
|
|||
int target_surface_height;
|
||||
|
||||
double frame_timer;
|
||||
double frame_last_returned_time;
|
||||
int video_stream;
|
||||
AVStream *video_st;
|
||||
M_PACKET_QUEUE videoq;
|
||||
|
@ -277,16 +282,13 @@ static int M_PacketQueuePutPrivate(M_PACKET_QUEUE *q, AVPacket *pkt)
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (av_fifo_space(q->pkt_list) < (signed)sizeof(pkt1)) {
|
||||
if (av_fifo_grow(q->pkt_list, sizeof(pkt1)) < 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
pkt1.pkt = pkt;
|
||||
pkt1.serial = q->serial;
|
||||
|
||||
av_fifo_generic_write(q->pkt_list, &pkt1, sizeof(pkt1), nullptr);
|
||||
int32_t ret = av_fifo_write(q->pkt_list, &pkt1, 1);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
q->nb_packets++;
|
||||
q->size += pkt1.pkt->size + sizeof(pkt1);
|
||||
q->duration += pkt1.pkt->duration;
|
||||
|
@ -327,8 +329,9 @@ static int M_PacketQueuePutNullPacket(
|
|||
static int M_PacketQueueInit(M_PACKET_QUEUE *q)
|
||||
{
|
||||
memset(q, 0, sizeof(M_PACKET_QUEUE));
|
||||
q->pkt_list = av_fifo_alloc(sizeof(M_PACKET_LIST));
|
||||
if (!q->pkt_list) {
|
||||
q->pkt_list =
|
||||
av_fifo_alloc2(1, sizeof(M_PACKET_LIST), AV_FIFO_FLAG_AUTO_GROW);
|
||||
if (q->pkt_list == nullptr) {
|
||||
return AVERROR(ENOMEM);
|
||||
}
|
||||
|
||||
|
@ -353,8 +356,7 @@ static void M_PacketQueueFlush(M_PACKET_QUEUE *q)
|
|||
M_PACKET_LIST pkt1;
|
||||
|
||||
SDL_LockMutex(q->mutex);
|
||||
while (av_fifo_size(q->pkt_list) >= (signed)sizeof(pkt1)) {
|
||||
av_fifo_generic_read(q->pkt_list, &pkt1, sizeof(pkt1), nullptr);
|
||||
while (av_fifo_read(q->pkt_list, &pkt1, 1) >= 0) {
|
||||
av_packet_free(&pkt1.pkt);
|
||||
}
|
||||
q->nb_packets = 0;
|
||||
|
@ -367,7 +369,7 @@ static void M_PacketQueueFlush(M_PACKET_QUEUE *q)
|
|||
static void M_PacketQueueDestroy(M_PACKET_QUEUE *q)
|
||||
{
|
||||
M_PacketQueueFlush(q);
|
||||
av_fifo_freep(&q->pkt_list);
|
||||
av_fifo_freep2(&q->pkt_list);
|
||||
SDL_DestroyMutex(q->mutex);
|
||||
SDL_DestroyCond(q->cond);
|
||||
}
|
||||
|
@ -402,8 +404,7 @@ static int M_PacketQueueGet(
|
|||
break;
|
||||
}
|
||||
|
||||
if (av_fifo_size(q->pkt_list) >= (signed)sizeof(pkt1)) {
|
||||
av_fifo_generic_read(q->pkt_list, &pkt1, sizeof(pkt1), nullptr);
|
||||
if (av_fifo_read(q->pkt_list, &pkt1, 1) >= 0) {
|
||||
q->nb_packets--;
|
||||
q->size -= pkt1.pkt->size + sizeof(pkt1);
|
||||
q->duration -= pkt1.pkt->duration;
|
||||
|
@ -518,6 +519,15 @@ static int M_DecoderDecodeFrame(M_DECODER *d, AVFrame *frame)
|
|||
av_packet_unref(d->pkt);
|
||||
}
|
||||
|
||||
if (d->pkt->buf && !d->pkt->opaque_ref) {
|
||||
d->pkt->opaque_ref = av_buffer_allocz(sizeof(M_FRAME_DATA));
|
||||
if (!d->pkt->opaque_ref) {
|
||||
return AVERROR(ENOMEM);
|
||||
}
|
||||
M_FRAME_DATA *fd = (M_FRAME_DATA *)d->pkt->opaque_ref->data;
|
||||
fd->pkt_pos = d->pkt->pos;
|
||||
}
|
||||
|
||||
if (avcodec_send_packet(d->avctx, d->pkt) == AVERROR(EAGAIN)) {
|
||||
LOG_ERROR(
|
||||
"Receive_frame and send_packet both returned EAGAIN, "
|
||||
|
@ -1109,37 +1119,52 @@ static int M_AudioThread(void *arg)
|
|||
M_STATE *is = arg;
|
||||
AVFrame *frame = av_frame_alloc();
|
||||
M_FRAME *af;
|
||||
int last_serial = -1;
|
||||
int got_frame = 0;
|
||||
AVRational tb;
|
||||
int ret = 0;
|
||||
|
||||
if (!frame) {
|
||||
if (frame == nullptr) {
|
||||
return AVERROR(ENOMEM);
|
||||
}
|
||||
|
||||
do {
|
||||
if ((got_frame = M_DecoderDecodeFrame(&is->auddec, frame)) < 0) {
|
||||
got_frame = M_DecoderDecodeFrame(&is->auddec, frame);
|
||||
if (got_frame < 0) {
|
||||
goto the_end;
|
||||
}
|
||||
|
||||
if (got_frame) {
|
||||
tb = (AVRational) { 1, frame->sample_rate };
|
||||
|
||||
if (!(af = M_FrameQueuePeekWritable(&is->sampq))) {
|
||||
M_FRAME_DATA *fd = frame->opaque_ref
|
||||
? (M_FRAME_DATA *)frame->opaque_ref->data
|
||||
: nullptr;
|
||||
af = M_FrameQueuePeekWritable(&is->sampq);
|
||||
if (af == nullptr) {
|
||||
goto the_end;
|
||||
}
|
||||
|
||||
af->pts =
|
||||
(frame->pts == AV_NOPTS_VALUE) ? NAN : frame->pts * av_q2d(tb);
|
||||
af->pos = frame->pkt_pos;
|
||||
af->pos = fd ? fd->pkt_pos : -1;
|
||||
af->serial = is->auddec.pkt_serial;
|
||||
af->duration =
|
||||
av_q2d((AVRational) { frame->nb_samples, frame->sample_rate });
|
||||
|
||||
av_frame_move_ref(af->frame, frame);
|
||||
M_FrameQueuePush(&is->sampq);
|
||||
|
||||
if (is->audioq.serial != is->auddec.pkt_serial) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (ret == AVERROR_EOF) {
|
||||
is->auddec.finished = is->auddec.pkt_serial;
|
||||
}
|
||||
}
|
||||
} while (ret >= 0 || ret == AVERROR(EAGAIN) || ret == AVERROR_EOF);
|
||||
|
||||
the_end:
|
||||
av_frame_free(&frame);
|
||||
return ret;
|
||||
|
@ -1180,17 +1205,23 @@ static int M_VideoThread(void *arg)
|
|||
continue;
|
||||
}
|
||||
|
||||
is->frame_last_returned_time = av_gettime_relative() / 1000000.0;
|
||||
|
||||
M_FRAME_DATA *fd = frame->opaque_ref
|
||||
? (M_FRAME_DATA *)frame->opaque_ref->data
|
||||
: nullptr;
|
||||
|
||||
duration =
|
||||
(frame_rate.num && frame_rate.den
|
||||
? av_q2d((AVRational) { frame_rate.den, frame_rate.num })
|
||||
: 0);
|
||||
pts = (frame->pts == AV_NOPTS_VALUE) ? NAN : frame->pts * av_q2d(tb);
|
||||
ret = M_QueuePicture(
|
||||
is, frame, pts, duration, frame->pkt_pos, is->viddec.pkt_serial);
|
||||
is, frame, pts, duration, fd ? fd->pkt_pos : -1,
|
||||
is->viddec.pkt_serial);
|
||||
av_frame_unref(frame);
|
||||
|
||||
if (ret < 0) {
|
||||
goto the_end;
|
||||
if (is->videoq.serial != is->viddec.pkt_serial) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
the_end:
|
||||
|
@ -1240,6 +1271,7 @@ static int M_SynchronizeAudio(M_STATE *is, int nb_samples)
|
|||
|
||||
static int M_AudioDecodeFrame(M_STATE *is)
|
||||
{
|
||||
|
||||
int data_size, resampled_data_size;
|
||||
av_unused double audio_clock0;
|
||||
int wanted_nb_samples;
|
||||
|
@ -1250,6 +1282,15 @@ static int M_AudioDecodeFrame(M_STATE *is)
|
|||
}
|
||||
|
||||
do {
|
||||
#if defined(_WIN32)
|
||||
while (M_FrameQueueNBRemaining(&is->sampq) == 0) {
|
||||
if ((av_gettime_relative() - m_AudioCallbackTime) > 1000000LL
|
||||
* is->audio_hw_buf_size / is->audio_tgt.bytes_per_sec / 2) {
|
||||
return -1;
|
||||
}
|
||||
av_usleep(1000);
|
||||
}
|
||||
#endif
|
||||
if (!(af = M_FrameQueuePeekReadable(&is->sampq))) {
|
||||
return -1;
|
||||
}
|
||||
|
@ -1257,39 +1298,39 @@ static int M_AudioDecodeFrame(M_STATE *is)
|
|||
} while (af->serial != is->audioq.serial);
|
||||
|
||||
data_size = av_samples_get_buffer_size(
|
||||
nullptr, af->frame->channels, af->frame->nb_samples, af->frame->format,
|
||||
1);
|
||||
nullptr, af->frame->ch_layout.nb_channels, af->frame->nb_samples,
|
||||
af->frame->format, 1);
|
||||
|
||||
int64_t dec_channel_layout =
|
||||
(af->frame->channel_layout
|
||||
&& af->frame->channels
|
||||
== av_get_channel_layout_nb_channels(af->frame->channel_layout))
|
||||
? (signed)af->frame->channel_layout
|
||||
: av_get_default_channel_layout(af->frame->channels);
|
||||
wanted_nb_samples = M_SynchronizeAudio(is, af->frame->nb_samples);
|
||||
|
||||
if (af->frame->format != is->audio_src.fmt
|
||||
|| dec_channel_layout != is->audio_src.channel_layout
|
||||
|| av_channel_layout_compare(
|
||||
&af->frame->ch_layout, &is->audio_src.ch_layout)
|
||||
|| af->frame->sample_rate != is->audio_src.freq
|
||||
|| (wanted_nb_samples != af->frame->nb_samples && !is->swr_ctx)) {
|
||||
int ret;
|
||||
swr_free(&is->swr_ctx);
|
||||
is->swr_ctx = swr_alloc_set_opts(
|
||||
nullptr, is->audio_tgt.channel_layout, is->audio_tgt.fmt,
|
||||
is->audio_tgt.freq, dec_channel_layout, af->frame->format,
|
||||
ret = swr_alloc_set_opts2(
|
||||
&is->swr_ctx, &is->audio_tgt.ch_layout, is->audio_tgt.fmt,
|
||||
is->audio_tgt.freq, &af->frame->ch_layout, af->frame->format,
|
||||
af->frame->sample_rate, 0, nullptr);
|
||||
if (!is->swr_ctx || swr_init(is->swr_ctx) < 0) {
|
||||
if (ret < 0 || swr_init(is->swr_ctx) < 0) {
|
||||
LOG_ERROR(
|
||||
"Cannot create sample rate converter for conversion of %d Hz "
|
||||
"%s %d channels to %d Hz %s %d channels!",
|
||||
af->frame->sample_rate,
|
||||
av_get_sample_fmt_name(af->frame->format), af->frame->channels,
|
||||
is->audio_tgt.freq, av_get_sample_fmt_name(is->audio_tgt.fmt),
|
||||
is->audio_tgt.channels);
|
||||
av_get_sample_fmt_name(af->frame->format),
|
||||
af->frame->ch_layout.nb_channels, is->audio_tgt.freq,
|
||||
av_get_sample_fmt_name(is->audio_tgt.fmt),
|
||||
is->audio_tgt.ch_layout.nb_channels);
|
||||
swr_free(&is->swr_ctx);
|
||||
return -1;
|
||||
}
|
||||
is->audio_src.channel_layout = dec_channel_layout;
|
||||
is->audio_src.channels = af->frame->channels;
|
||||
if (av_channel_layout_copy(
|
||||
&is->audio_src.ch_layout, &af->frame->ch_layout)
|
||||
< 0) {
|
||||
return -1;
|
||||
}
|
||||
is->audio_src.freq = af->frame->sample_rate;
|
||||
is->audio_src.fmt = af->frame->format;
|
||||
}
|
||||
|
@ -1301,7 +1342,8 @@ static int M_AudioDecodeFrame(M_STATE *is)
|
|||
/ af->frame->sample_rate
|
||||
+ 256;
|
||||
int out_size = av_samples_get_buffer_size(
|
||||
nullptr, is->audio_tgt.channels, out_count, is->audio_tgt.fmt, 0);
|
||||
nullptr, is->audio_tgt.ch_layout.nb_channels, out_count,
|
||||
is->audio_tgt.fmt, 0);
|
||||
int len2;
|
||||
if (out_size < 0) {
|
||||
LOG_ERROR("av_samples_get_buffer_size() failed");
|
||||
|
@ -1330,12 +1372,13 @@ static int M_AudioDecodeFrame(M_STATE *is)
|
|||
return -1;
|
||||
}
|
||||
if (len2 == out_count) {
|
||||
LOG_ERROR("audio buffer is probably too small");
|
||||
if (swr_init(is->swr_ctx) < 0) {
|
||||
swr_free(&is->swr_ctx);
|
||||
}
|
||||
}
|
||||
is->audio_buf = is->audio_buf1;
|
||||
resampled_data_size = len2 * is->audio_tgt.channels
|
||||
resampled_data_size = len2 * is->audio_tgt.ch_layout.nb_channels
|
||||
* av_get_bytes_per_sample(is->audio_tgt.fmt);
|
||||
} else {
|
||||
is->audio_buf = af->frame->data[0];
|
||||
|
@ -1404,29 +1447,27 @@ static void M_SDLAudioCallback(void *opaque, Uint8 *stream, int len)
|
|||
}
|
||||
|
||||
static int M_AudioOpen(
|
||||
M_STATE *is, int64_t wanted_channel_layout, int wanted_nb_channels,
|
||||
int wanted_sample_rate, M_AUDIO_PARAMS *audio_hw_params)
|
||||
M_STATE *is, AVChannelLayout *wanted_channel_layout, int wanted_sample_rate,
|
||||
M_AUDIO_PARAMS *audio_hw_params)
|
||||
{
|
||||
SDL_AudioSpec wanted_spec, spec;
|
||||
const char *env;
|
||||
static const int next_nb_channels[] = { 0, 0, 1, 6, 2, 6, 4, 6 };
|
||||
static const int next_sample_rates[] = { 0, 44100, 48000, 96000, 192000 };
|
||||
int next_sample_rate_idx = FF_ARRAY_ELEMS(next_sample_rates) - 1;
|
||||
int wanted_nb_channels = wanted_channel_layout->nb_channels;
|
||||
|
||||
const char *const env = SDL_getenv("SDL_AUDIO_CHANNELS");
|
||||
env = SDL_getenv("SDL_AUDIO_CHANNELS");
|
||||
if (env) {
|
||||
wanted_nb_channels = atoi(env);
|
||||
wanted_channel_layout =
|
||||
av_get_default_channel_layout(wanted_nb_channels);
|
||||
av_channel_layout_uninit(wanted_channel_layout);
|
||||
av_channel_layout_default(wanted_channel_layout, wanted_nb_channels);
|
||||
}
|
||||
if (!wanted_channel_layout
|
||||
|| wanted_nb_channels
|
||||
!= av_get_channel_layout_nb_channels(wanted_channel_layout)) {
|
||||
wanted_channel_layout =
|
||||
av_get_default_channel_layout(wanted_nb_channels);
|
||||
wanted_channel_layout &= ~AV_CH_LAYOUT_STEREO_DOWNMIX;
|
||||
if (wanted_channel_layout->order != AV_CHANNEL_ORDER_NATIVE) {
|
||||
av_channel_layout_uninit(wanted_channel_layout);
|
||||
av_channel_layout_default(wanted_channel_layout, wanted_nb_channels);
|
||||
}
|
||||
wanted_nb_channels =
|
||||
av_get_channel_layout_nb_channels(wanted_channel_layout);
|
||||
wanted_nb_channels = wanted_channel_layout->nb_channels;
|
||||
wanted_spec.channels = wanted_nb_channels;
|
||||
wanted_spec.freq = wanted_sample_rate;
|
||||
if (wanted_spec.freq <= 0 || wanted_spec.channels <= 0) {
|
||||
|
@ -1448,6 +1489,9 @@ static int M_AudioOpen(
|
|||
nullptr, 0, &wanted_spec, &spec,
|
||||
SDL_AUDIO_ALLOW_FREQUENCY_CHANGE
|
||||
| SDL_AUDIO_ALLOW_CHANNELS_CHANGE))) {
|
||||
LOG_WARNING(
|
||||
"SDL_OpenAudio (%d channels, %d Hz): %s", wanted_spec.channels,
|
||||
wanted_spec.freq, SDL_GetError());
|
||||
wanted_spec.channels = next_nb_channels[FFMIN(7, wanted_spec.channels)];
|
||||
if (!wanted_spec.channels) {
|
||||
wanted_spec.freq = next_sample_rates[next_sample_rate_idx--];
|
||||
|
@ -1457,16 +1501,16 @@ static int M_AudioOpen(
|
|||
return -1;
|
||||
}
|
||||
}
|
||||
wanted_channel_layout =
|
||||
av_get_default_channel_layout(wanted_spec.channels);
|
||||
av_channel_layout_default(wanted_channel_layout, wanted_spec.channels);
|
||||
}
|
||||
if (spec.format != AUDIO_S16SYS) {
|
||||
LOG_ERROR("SDL advised audio format %d is not supported!", spec.format);
|
||||
return -1;
|
||||
}
|
||||
if (spec.channels != wanted_spec.channels) {
|
||||
wanted_channel_layout = av_get_default_channel_layout(spec.channels);
|
||||
if (!wanted_channel_layout) {
|
||||
av_channel_layout_uninit(wanted_channel_layout);
|
||||
av_channel_layout_default(wanted_channel_layout, spec.channels);
|
||||
if (wanted_channel_layout->order != AV_CHANNEL_ORDER_NATIVE) {
|
||||
LOG_ERROR(
|
||||
"SDL advised channel count %d is not supported!",
|
||||
spec.channels);
|
||||
|
@ -1476,12 +1520,15 @@ static int M_AudioOpen(
|
|||
|
||||
audio_hw_params->fmt = AV_SAMPLE_FMT_S16;
|
||||
audio_hw_params->freq = spec.freq;
|
||||
audio_hw_params->channel_layout = wanted_channel_layout;
|
||||
audio_hw_params->channels = spec.channels;
|
||||
if (av_channel_layout_copy(
|
||||
&audio_hw_params->ch_layout, wanted_channel_layout)
|
||||
< 0)
|
||||
return -1;
|
||||
audio_hw_params->frame_size = av_samples_get_buffer_size(
|
||||
nullptr, audio_hw_params->channels, 1, audio_hw_params->fmt, 1);
|
||||
nullptr, audio_hw_params->ch_layout.nb_channels, 1,
|
||||
audio_hw_params->fmt, 1);
|
||||
audio_hw_params->bytes_per_sec = av_samples_get_buffer_size(
|
||||
nullptr, audio_hw_params->channels, audio_hw_params->freq,
|
||||
nullptr, audio_hw_params->ch_layout.nb_channels, audio_hw_params->freq,
|
||||
audio_hw_params->fmt, 1);
|
||||
if (audio_hw_params->bytes_per_sec <= 0
|
||||
|| audio_hw_params->frame_size <= 0) {
|
||||
|
@ -1501,7 +1548,7 @@ static int M_StreamComponentOpen(M_STATE *is, int stream_index)
|
|||
const AVDictionaryEntry *t = nullptr;
|
||||
int sample_rate;
|
||||
int nb_channels;
|
||||
int64_t channel_layout;
|
||||
AVChannelLayout ch_layout;
|
||||
int ret = 0;
|
||||
|
||||
if (stream_index < 0 || stream_index >= (signed)ic->nb_streams) {
|
||||
|
@ -1542,11 +1589,9 @@ static int M_StreamComponentOpen(M_STATE *is, int stream_index)
|
|||
switch (avctx->codec_type) {
|
||||
case AVMEDIA_TYPE_AUDIO:
|
||||
sample_rate = avctx->sample_rate;
|
||||
nb_channels = avctx->channels;
|
||||
channel_layout = avctx->channel_layout;
|
||||
ch_layout = avctx->ch_layout;
|
||||
|
||||
if ((ret = M_AudioOpen(
|
||||
is, channel_layout, nb_channels, sample_rate, &is->audio_tgt))
|
||||
if ((ret = M_AudioOpen(is, &ch_layout, sample_rate, &is->audio_tgt))
|
||||
< 0) {
|
||||
goto fail;
|
||||
}
|
||||
|
@ -1568,9 +1613,7 @@ static int M_StreamComponentOpen(M_STATE *is, int stream_index)
|
|||
< 0) {
|
||||
goto fail;
|
||||
}
|
||||
if ((is->ic->iformat->flags
|
||||
& (AVFMT_NOBINSEARCH | AVFMT_NOGENSEARCH | AVFMT_NO_BYTE_SEEK))
|
||||
&& !is->ic->iformat->read_seek) {
|
||||
if (is->ic->iformat->flags & AVFMT_NOTIMESTAMPS) {
|
||||
is->auddec.start_pts = is->audio_st->start_time;
|
||||
is->auddec.start_pts_tb = is->audio_st->time_base;
|
||||
}
|
||||
|
@ -1606,8 +1649,9 @@ static int M_StreamComponentOpen(M_STATE *is, int stream_index)
|
|||
|
||||
fail:
|
||||
avcodec_free_context(&avctx);
|
||||
|
||||
out:
|
||||
av_channel_layout_uninit(&ch_layout);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -53,7 +53,7 @@ RUN apt-get install -y \
|
|||
zlib1g-dev
|
||||
RUN git clone \
|
||||
--depth 1 \
|
||||
--branch "n4.4.1" \
|
||||
--branch "n7.1" \
|
||||
https://github.com/FFmpeg/FFmpeg
|
||||
COPY ./tools/ffmpeg_flags.txt /tmp/ffmpeg_flags.txt
|
||||
RUN cd FFmpeg \
|
||||
|
|
|
@ -54,7 +54,7 @@ RUN apt-get install -y \
|
|||
nasm
|
||||
RUN git clone \
|
||||
--depth 1 \
|
||||
--branch "n4.4.1" \
|
||||
--branch "n7.1" \
|
||||
https://github.com/FFmpeg/FFmpeg
|
||||
COPY --from=zlib /ext/ /usr/i686-w64-mingw32/
|
||||
COPY ./tools/ffmpeg_flags.txt /tmp/ffmpeg_flags.txt
|
||||
|
@ -65,6 +65,8 @@ RUN cd FFmpeg \
|
|||
--cross-prefix=i686-w64-mingw32- \
|
||||
--prefix=/ext/ \
|
||||
--cc=i686-w64-mingw32-gcc \
|
||||
--cxx=i686-w64-mingw32-g++ \
|
||||
--host-cc=i686-w64-mingw32-gcc \
|
||||
--strip=i686-w64-mingw32-strip \
|
||||
--pkg-config=i686-w64-mingw32-pkg-config \
|
||||
--enable-static \
|
||||
|
|
|
@ -53,7 +53,7 @@ RUN apt-get install -y \
|
|||
zlib1g-dev
|
||||
RUN git clone \
|
||||
--depth 1 \
|
||||
--branch "n4.4.1" \
|
||||
--branch "n7.1" \
|
||||
https://github.com/FFmpeg/FFmpeg
|
||||
COPY ./tools/ffmpeg_flags.txt /tmp/ffmpeg_flags.txt
|
||||
RUN cd FFmpeg \
|
||||
|
|
|
@ -56,7 +56,7 @@ RUN apt-get install -y \
|
|||
nasm
|
||||
RUN git clone \
|
||||
--depth 1 \
|
||||
--branch "n4.4.1" \
|
||||
--branch "n7.1" \
|
||||
https://github.com/FFmpeg/FFmpeg
|
||||
COPY --from=zlib /ext/ /usr/i686-w64-mingw32/
|
||||
COPY ./tools/ffmpeg_flags.txt /tmp/ffmpeg_flags.txt
|
||||
|
@ -67,6 +67,8 @@ RUN cd FFmpeg \
|
|||
--cross-prefix=i686-w64-mingw32- \
|
||||
--prefix=/ext/ \
|
||||
--cc=i686-w64-mingw32-gcc \
|
||||
--cxx=i686-w64-mingw32-g++ \
|
||||
--host-cc=i686-w64-mingw32-gcc \
|
||||
--strip=i686-w64-mingw32-strip \
|
||||
--pkg-config=i686-w64-mingw32-pkg-config \
|
||||
--enable-static \
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue