diff options
Diffstat (limited to 'audio')
-rw-r--r-- | audio/decode/ad.h | 49 | ||||
-rw-r--r-- | audio/decode/ad_lavc.c | 130 | ||||
-rw-r--r-- | audio/decode/ad_spdif.c | 158 | ||||
-rw-r--r-- | audio/decode/dec_audio.c | 309 | ||||
-rw-r--r-- | audio/decode/dec_audio.h | 66 |
5 files changed, 163 insertions, 549 deletions
diff --git a/audio/decode/ad.h b/audio/decode/ad.h deleted file mode 100644 index a8384c277f..0000000000 --- a/audio/decode/ad.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * This file is part of mpv. - * - * mpv is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * mpv is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with mpv. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef MPLAYER_AD_H -#define MPLAYER_AD_H - -#include "common/codecs.h" -#include "demux/stheader.h" -#include "demux/demux.h" - -#include "audio/format.h" -#include "audio/aframe.h" -#include "dec_audio.h" - -struct mp_decoder_list; - -/* interface of audio decoder drivers */ -struct ad_functions { - const char *name; - void (*add_decoders)(struct mp_decoder_list *list); - int (*init)(struct dec_audio *da, const char *decoder); - void (*uninit)(struct dec_audio *da); - int (*control)(struct dec_audio *da, int cmd, void *arg); - // Return whether or not the packet has been consumed. - bool (*send_packet)(struct dec_audio *da, struct demux_packet *pkt); - // Return whether decoding is still going on (false if EOF was reached). - // Never returns false & *out set, but can return true with !*out. - bool (*receive_frame)(struct dec_audio *da, struct mp_aframe **out); -}; - -enum ad_ctrl { - ADCTRL_RESET = 1, // flush and reset state, e.g. after seeking -}; - -#endif /* MPLAYER_AD_H */ diff --git a/audio/decode/ad_lavc.c b/audio/decode/ad_lavc.c index fb429d567b..7713a506a6 100644 --- a/audio/decode/ad_lavc.c +++ b/audio/decode/ad_lavc.c @@ -27,27 +27,30 @@ #include <libavutil/intreadwrite.h> #include "mpv_talloc.h" - -#include "config.h" +#include "audio/aframe.h" +#include "audio/fmt-conversion.h" #include "common/av_common.h" #include "common/codecs.h" +#include "common/global.h" #include "common/msg.h" +#include "demux/packet.h" +#include "demux/stheader.h" +#include "filters/f_decoder_wrapper.h" +#include "filters/filter_internal.h" #include "options/options.h" -#include "ad.h" -#include "audio/fmt-conversion.h" - struct priv { AVCodecContext *avctx; AVFrame *avframe; - bool force_channel_map; + struct mp_chmap force_channel_map; uint32_t skip_samples, trim_samples; bool preroll_done; double next_pts; AVRational codec_timebase; -}; + bool eof_returned; -static void uninit(struct dec_audio *da); + struct mp_decoder public; +}; #define OPT_BASE_STRUCT struct ad_lavc_params struct ad_lavc_params { @@ -73,26 +76,24 @@ const struct m_sub_options ad_lavc_conf = { }, }; -static int init(struct dec_audio *da, const char *decoder) +static bool init(struct mp_filter *da, struct mp_codec_params *codec, + const char *decoder) { - struct MPOpts *mpopts = da->opts; + struct priv *ctx = da->priv; + struct MPOpts *mpopts = da->global->opts; struct ad_lavc_params *opts = mpopts->ad_lavc_params; AVCodecContext *lavc_context; AVCodec *lavc_codec; - struct mp_codec_params *c = da->codec; - - struct priv *ctx = talloc_zero(NULL, struct priv); - da->priv = ctx; - ctx->codec_timebase = mp_get_codec_timebase(da->codec); + ctx->codec_timebase = mp_get_codec_timebase(codec); - ctx->force_channel_map = c->force_channels; + if (codec->force_channels) + ctx->force_channel_map = codec->channels; lavc_codec = avcodec_find_decoder_by_name(decoder); if (!lavc_codec) { MP_ERR(da, "Cannot find codec '%s' in libavcodec...\n", decoder); - uninit(da); - return 0; + return false; } lavc_context = avcodec_alloc_context3(lavc_codec); @@ -121,10 +122,9 @@ static int init(struct dec_audio *da, const char *decoder) mp_set_avopts(da->log, lavc_context, opts->avopts); - if (mp_set_avctx_codec_headers(lavc_context, c) < 0) { + if (mp_set_avctx_codec_headers(lavc_context, codec) < 0) { MP_ERR(da, "Could not set decoder parameters.\n"); - uninit(da); - return 0; + return false; } mp_set_avcodec_threads(da->log, lavc_context, opts->threads); @@ -132,41 +132,35 @@ static int init(struct dec_audio *da, const char *decoder) /* open it */ if (avcodec_open2(lavc_context, lavc_codec, NULL) < 0) { MP_ERR(da, "Could not open codec.\n"); - uninit(da); - return 0; + return false; } ctx->next_pts = MP_NOPTS_VALUE; - return 1; + return true; } -static void uninit(struct dec_audio *da) +static void destroy(struct mp_filter *da) { struct priv *ctx = da->priv; - if (!ctx) - return; avcodec_free_context(&ctx->avctx); av_frame_free(&ctx->avframe); } -static int control(struct dec_audio *da, int cmd, void *arg) +static void reset(struct mp_filter *da) { struct priv *ctx = da->priv; - switch (cmd) { - case ADCTRL_RESET: - avcodec_flush_buffers(ctx->avctx); - ctx->skip_samples = 0; - ctx->trim_samples = 0; - ctx->preroll_done = false; - ctx->next_pts = MP_NOPTS_VALUE; - return CONTROL_TRUE; - } - return CONTROL_UNKNOWN; + + avcodec_flush_buffers(ctx->avctx); + ctx->skip_samples = 0; + ctx->trim_samples = 0; + ctx->preroll_done = false; + ctx->next_pts = MP_NOPTS_VALUE; + ctx->eof_returned = false; } -static bool send_packet(struct dec_audio *da, struct demux_packet *mpkt) +static bool send_packet(struct mp_filter *da, struct demux_packet *mpkt) { struct priv *priv = da->priv; AVCodecContext *avctx = priv->avctx; @@ -190,7 +184,7 @@ static bool send_packet(struct dec_audio *da, struct demux_packet *mpkt) return true; } -static bool receive_frame(struct dec_audio *da, struct mp_aframe **out) +static bool receive_frame(struct mp_filter *da, struct mp_frame *out) { struct priv *priv = da->priv; AVCodecContext *avctx = priv->avctx; @@ -200,7 +194,8 @@ static bool receive_frame(struct dec_audio *da, struct mp_aframe **out) if (ret == AVERROR_EOF) { // If flushing was initialized earlier and has ended now, make it start // over in case we get new packets at some point in the future. - control(da, ADCTRL_RESET, NULL); + // (Dont' reset the filter itself, we want to keep other state.) + avcodec_flush_buffers(priv->avctx); return false; } else if (ret < 0 && ret != AVERROR(EAGAIN)) { MP_ERR(da, "Error decoding audio.\n"); @@ -220,8 +215,8 @@ static bool receive_frame(struct dec_audio *da, struct mp_aframe **out) if (!mpframe) return true; - if (priv->force_channel_map) - mp_aframe_set_chmap(mpframe, &da->codec->channels); + if (priv->force_channel_map.num) + mp_aframe_set_chmap(mpframe, &priv->force_channel_map); if (out_pts == MP_NOPTS_VALUE) out_pts = priv->next_pts; @@ -257,24 +252,57 @@ static bool receive_frame(struct dec_audio *da, struct mp_aframe **out) priv->trim_samples -= trim; } - *out = mpframe; + *out = MAKE_FRAME(MP_FRAME_AUDIO, mpframe); av_frame_unref(priv->avframe); return true; } +static void process(struct mp_filter *ad) +{ + struct priv *priv = ad->priv; + + lavc_process(ad, &priv->eof_returned, send_packet, receive_frame); +} + +static const struct mp_filter_info ad_lavc_filter = { + .name = "ad_lavc", + .priv_size = sizeof(struct priv), + .process = process, + .reset = reset, + .destroy = destroy, +}; + +static struct mp_decoder *create(struct mp_filter *parent, + struct mp_codec_params *codec, + const char *decoder) +{ + struct mp_filter *da = mp_filter_create(parent, &ad_lavc_filter); + if (!da) + return NULL; + + mp_filter_add_pin(da, MP_PIN_IN, "in"); + mp_filter_add_pin(da, MP_PIN_OUT, "out"); + + da->log = mp_log_new(da, parent->log, NULL); + + struct priv *priv = da->priv; + priv->public.f = da; + + if (!init(da, codec, decoder)) { + talloc_free(da); + return NULL; + } + return &priv->public; +} + static void add_decoders(struct mp_decoder_list *list) { mp_add_lavc_decoders(list, AVMEDIA_TYPE_AUDIO); } -const struct ad_functions ad_lavc = { - .name = "lavc", +const struct mp_decoder_fns ad_lavc = { + .create = create, .add_decoders = add_decoders, - .init = init, - .uninit = uninit, - .control = control, - .send_packet = send_packet, - .receive_frame = receive_frame, }; diff --git a/audio/decode/ad_spdif.c b/audio/decode/ad_spdif.c index cc800224e9..c97c62ddaa 100644 --- a/audio/decode/ad_spdif.c +++ b/audio/decode/ad_spdif.c @@ -24,11 +24,16 @@ #include <libavcodec/avcodec.h> #include <libavutil/opt.h> -#include "config.h" -#include "common/msg.h" +#include "audio/aframe.h" +#include "audio/format.h" #include "common/av_common.h" +#include "common/codecs.h" +#include "common/msg.h" +#include "demux/packet.h" +#include "demux/stheader.h" +#include "filters/f_decoder_wrapper.h" +#include "filters/filter_internal.h" #include "options/options.h" -#include "ad.h" #define OUTBUF_SIZE 65536 @@ -43,8 +48,8 @@ struct spdifContext { struct mp_aframe *fmt; int sstride; struct mp_aframe_pool *pool; - bool got_eof; - struct demux_packet *queued_packet; + + struct mp_decoder public; }; static int write_packet(void *p, uint8_t *buf, int buf_size) @@ -62,7 +67,8 @@ static int write_packet(void *p, uint8_t *buf, int buf_size) return buf_size; } -static void uninit(struct dec_audio *da) +// (called on both filter destruction _and_ if lavf fails to init) +static void destroy(struct mp_filter *da) { struct spdifContext *spdif_ctx = da->priv; AVFormatContext *lavf_ctx = spdif_ctx->lavf_ctx; @@ -74,26 +80,11 @@ static void uninit(struct dec_audio *da) av_freep(&lavf_ctx->pb->buffer); av_freep(&lavf_ctx->pb); avformat_free_context(lavf_ctx); - talloc_free(spdif_ctx->queued_packet); spdif_ctx->lavf_ctx = NULL; } } -static int init(struct dec_audio *da, const char *decoder) -{ - struct spdifContext *spdif_ctx = talloc_zero(NULL, struct spdifContext); - da->priv = spdif_ctx; - spdif_ctx->log = da->log; - spdif_ctx->pool = mp_aframe_pool_create(spdif_ctx); - - if (strcmp(decoder, "spdif_dts_hd") == 0) - spdif_ctx->use_dts_hd = true; - - spdif_ctx->codec_id = mp_codec_to_av_codec_id(da->codec->codec); - return spdif_ctx->codec_id != AV_CODEC_ID_NONE; -} - -static void determine_codec_params(struct dec_audio *da, AVPacket *pkt, +static void determine_codec_params(struct mp_filter *da, AVPacket *pkt, int *out_profile, int *out_rate) { struct spdifContext *spdif_ctx = da->priv; @@ -156,7 +147,7 @@ done: MP_WARN(da, "Failed to parse codec profile.\n"); } -static int init_filter(struct dec_audio *da, AVPacket *pkt) +static int init_filter(struct mp_filter *da, AVPacket *pkt) { struct spdifContext *spdif_ctx = da->priv; @@ -270,39 +261,36 @@ static int init_filter(struct dec_audio *da, AVPacket *pkt) return 0; fail: - uninit(da); + destroy(da); + mp_filter_internal_mark_failed(da); return -1; } - -static bool send_packet(struct dec_audio *da, struct demux_packet *mpkt) +static void process(struct mp_filter *da) { struct spdifContext *spdif_ctx = da->priv; - if (spdif_ctx->queued_packet || spdif_ctx->got_eof) - return false; - - spdif_ctx->queued_packet = mpkt ? demux_copy_packet(mpkt) : NULL; - spdif_ctx->got_eof = !mpkt; - return true; -} - -static bool receive_frame(struct dec_audio *da, struct mp_aframe **out) -{ - struct spdifContext *spdif_ctx = da->priv; + if (!mp_pin_can_transfer_data(da->ppins[1], da->ppins[0])) + return; - if (spdif_ctx->got_eof) { - spdif_ctx->got_eof = false; - return false; + struct mp_frame inframe = mp_pin_out_read(da->ppins[0]); + if (inframe.type == MP_FRAME_EOF) { + mp_pin_in_write(da->ppins[1], inframe); + return; + } else if (inframe.type != MP_FRAME_PACKET) { + if (inframe.type) { + MP_ERR(da, "unknown frame type\n"); + mp_filter_internal_mark_failed(da); + } + return; } - if (!spdif_ctx->queued_packet) - return true; - - double pts = spdif_ctx->queued_packet->pts; + struct demux_packet *mpkt = inframe.data; + struct mp_aframe *out = NULL; + double pts = mpkt->pts; AVPacket pkt; - mp_set_av_packet(&pkt, spdif_ctx->queued_packet, NULL); + mp_set_av_packet(&pkt, mpkt, NULL); pkt.pts = pkt.dts = 0; if (!spdif_ctx->lavf_ctx) { if (init_filter(da, &pkt) < 0) @@ -316,39 +304,29 @@ static bool receive_frame(struct dec_audio *da, struct mp_aframe **out) goto done; } - *out = mp_aframe_new_ref(spdif_ctx->fmt); + out = mp_aframe_new_ref(spdif_ctx->fmt); int samples = spdif_ctx->out_buffer_len / spdif_ctx->sstride; - if (mp_aframe_pool_allocate(spdif_ctx->pool, *out, samples) < 0) { - TA_FREEP(out); + if (mp_aframe_pool_allocate(spdif_ctx->pool, out, samples) < 0) { + TA_FREEP(&out); goto done; } - uint8_t **data = mp_aframe_get_data_rw(*out); + uint8_t **data = mp_aframe_get_data_rw(out); if (!data) { - TA_FREEP(out); + TA_FREEP(&out); goto done; } memcpy(data[0], spdif_ctx->out_buffer, spdif_ctx->out_buffer_len); - mp_aframe_set_pts(*out, pts); + mp_aframe_set_pts(out, pts); done: - talloc_free(spdif_ctx->queued_packet); - spdif_ctx->queued_packet = NULL; - return true; -} - -static int control(struct dec_audio *da, int cmd, void *arg) -{ - struct spdifContext *spdif_ctx = da->priv; - switch (cmd) { - case ADCTRL_RESET: - talloc_free(spdif_ctx->queued_packet); - spdif_ctx->queued_packet = NULL; - spdif_ctx->got_eof = false; - return CONTROL_TRUE; + talloc_free(mpkt); + if (out) { + mp_pin_in_write(da->ppins[1], MAKE_FRAME(MP_FRAME_AUDIO, out)); + } else { + mp_filter_internal_mark_failed(da); } - return CONTROL_UNKNOWN; } static const int codecs[] = { @@ -405,12 +383,44 @@ struct mp_decoder_list *select_spdif_codec(const char *codec, const char *pref) return list; } -const struct ad_functions ad_spdif = { - .name = "spdif", - .add_decoders = NULL, - .init = init, - .uninit = uninit, - .control = control, - .send_packet = send_packet, - .receive_frame = receive_frame, +static const struct mp_filter_info ad_spdif_filter = { + .name = "ad_spdif", + .priv_size = sizeof(struct spdifContext), + .process = process, + .destroy = destroy, +}; + +static struct mp_decoder *create(struct mp_filter *parent, + struct mp_codec_params *codec, + const char *decoder) +{ + struct mp_filter *da = mp_filter_create(parent, &ad_spdif_filter); + if (!da) + return NULL; + + mp_filter_add_pin(da, MP_PIN_IN, "in"); + mp_filter_add_pin(da, MP_PIN_OUT, "out"); + + da->log = mp_log_new(da, parent->log, NULL); + + struct spdifContext *spdif_ctx = da->priv; + spdif_ctx->log = da->log; + spdif_ctx->pool = mp_aframe_pool_create(spdif_ctx); + spdif_ctx->public.f = da; + + if (strcmp(decoder, "spdif_dts_hd") == 0) + spdif_ctx->use_dts_hd = true; + + spdif_ctx->codec_id = mp_codec_to_av_codec_id(codec->codec); + + + if (spdif_ctx->codec_id == AV_CODEC_ID_NONE) { + talloc_free(da); + return NULL; + } + return &spdif_ctx->public; +} + +const struct mp_decoder_fns ad_spdif = { + .create = create, }; diff --git a/audio/decode/dec_audio.c b/audio/decode/dec_audio.c deleted file mode 100644 index 111f981690..0000000000 --- a/audio/decode/dec_audio.c +++ /dev/null @@ -1,309 +0,0 @@ -/* - * This file is part of mpv. - * - * mpv is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * mpv is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with mpv. If not, see <http://www.gnu.org/licenses/>. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <math.h> -#include <assert.h> - -#include <libavutil/mem.h> - -#include "demux/codec_tags.h" - -#include "common/codecs.h" -#include "common/msg.h" -#include "common/recorder.h" -#include "misc/bstr.h" -#include "options/options.h" - -#include "stream/stream.h" -#include "demux/demux.h" - -#include "demux/stheader.h" - -#include "dec_audio.h" -#include "ad.h" -#include "audio/format.h" - -extern const struct ad_functions ad_lavc; - -// Not a real codec - specially treated. -extern const struct ad_functions ad_spdif; - -static const struct ad_functions * const ad_drivers[] = { - &ad_lavc, - NULL -}; - -static void uninit_decoder(struct dec_audio *d_audio) -{ - audio_reset_decoding(d_audio); - if (d_audio->ad_driver) { - MP_VERBOSE(d_audio, "Uninit audio decoder.\n"); - d_audio->ad_driver->uninit(d_audio); - } - d_audio->ad_driver = NULL; - talloc_free(d_audio->priv); - d_audio->priv = NULL; -} - -static int init_audio_codec(struct dec_audio *d_audio, const char *decoder) -{ - if (!d_audio->ad_driver->init(d_audio, decoder)) { - MP_VERBOSE(d_audio, "Audio decoder init failed.\n"); - d_audio->ad_driver = NULL; - uninit_decoder(d_audio); - return 0; - } - - return 1; -} - -struct mp_decoder_list *audio_decoder_list(void) -{ - struct mp_decoder_list *list = talloc_zero(NULL, struct mp_decoder_list); - for (int i = 0; ad_drivers[i] != NULL; i++) - ad_drivers[i]->add_decoders(list); - return list; -} - -static struct mp_decoder_list *audio_select_decoders(struct dec_audio *d_audio) -{ - struct MPOpts *opts = d_audio->opts; - const char *codec = d_audio->codec->codec; - - struct mp_decoder_list *list = audio_decoder_list(); - struct mp_decoder_list *new = - mp_select_decoders(d_audio->log, list, codec, opts->audio_decoders); - if (d_audio->try_spdif && codec) { - struct mp_decoder_list *spdif = - select_spdif_codec(codec, opts->audio_spdif); - mp_append_decoders(spdif, new); - talloc_free(new); - new = spdif; - } - talloc_free(list); - return new; -} - -static const struct ad_functions *find_driver(const char *name) -{ - for (int i = 0; ad_drivers[i] != NULL; i++) { - if (strcmp(ad_drivers[i]->name, name) == 0) - return ad_drivers[i]; - } - if (strcmp(name, "spdif") == 0) - return &ad_spdif; - return NULL; -} - -int audio_init_best_codec(struct dec_audio *d_audio) -{ - uninit_decoder(d_audio); - assert(!d_audio->ad_driver); - - struct mp_decoder_entry *decoder = NULL; - struct mp_decoder_list *list = audio_select_decoders(d_audio); - - mp_print_decoders(d_audio->log, MSGL_V, "Codec list:", list); - - for (int n = 0; n < list->num_entries; n++) { - struct mp_decoder_entry *sel = &list->entries[n]; - const struct ad_functions *driver = find_driver(sel->family); - if (!driver) - continue; - MP_VERBOSE(d_audio, "Opening audio decoder %s\n", sel->decoder); - d_audio->ad_driver = driver; - if (init_audio_codec(d_audio, sel->decoder)) { - decoder = sel; - break; - } - MP_WARN(d_audio, "Audio decoder init failed for %s\n", sel->decoder); - } - - if (d_audio->ad_driver) { - d_audio->decoder_desc = - talloc_asprintf(d_audio, "%s (%s)", decoder->decoder, decoder->desc); - MP_VERBOSE(d_audio, "Selected audio codec: %s\n", d_audio->decoder_desc); - } else { - MP_ERR(d_audio, "Failed to initialize an audio decoder for codec '%s'.\n", - d_audio->codec->codec); - } - - talloc_free(list); - return !!d_audio->ad_driver; -} - -void audio_uninit(struct dec_audio *d_audio) -{ - if (!d_audio) - return; - uninit_decoder(d_audio); - talloc_free(d_audio); -} - -void audio_reset_decoding(struct dec_audio *d_audio) -{ - if (d_audio->ad_driver) - d_audio->ad_driver->control(d_audio, ADCTRL_RESET, NULL); - d_audio->pts = MP_NOPTS_VALUE; - talloc_free(d_audio->current_frame); - d_audio->current_frame = NULL; - talloc_free(d_audio->packet); - d_audio->packet = NULL; - talloc_free(d_audio->new_segment); - d_audio->new_segment = NULL; - d_audio->start = d_audio->end = MP_NOPTS_VALUE; -} - -static void fix_audio_pts(struct dec_audio *da) -{ - if (!da->current_frame) - return; - - double frame_pts = mp_aframe_get_pts(da->current_frame); - if (frame_pts != MP_NOPTS_VALUE) { - if (da->pts != MP_NOPTS_VALUE) - MP_STATS(da, "value %f audio-pts-err", da->pts - frame_pts); - - // Keep the interpolated timestamp if it doesn't deviate more - // than 1 ms from the real one. (MKV rounded timestamps.) - if (da->pts == MP_NOPTS_VALUE || fabs(da->pts - frame_pts) > 0.001) - da->pts = frame_pts; - } - - if (da->pts == MP_NOPTS_VALUE && da->header->missing_timestamps) - da->pts = 0; - - mp_aframe_set_pts(da->current_frame, da->pts); - - if (da->pts != MP_NOPTS_VALUE) - da->pts += mp_aframe_duration(da->current_frame); -} - -static bool is_new_segment(struct dec_audio *da, struct demux_packet *p) -{ - return p->segmented && - (p->start != da->start || p->end != da->end || p->codec != da->codec); -} - -static void feed_packet(struct dec_audio *da) -{ - if (da->current_frame || !da->ad_driver) - return; - - if (!da->packet && !da->new_segment && - demux_read_packet_async(da->header, &da->packet) == 0) - { - da->current_state = DATA_WAIT; - return; - } - - if (da->packet && is_new_segment(da, da->packet)) { - assert(!da->new_segment); - da->new_segment = da->packet; - da->packet = NULL; - } - - if (da->ad_driver->send_packet(da, da->packet)) { - if (da->recorder_sink) - mp_recorder_feed_packet(da->recorder_sink, da->packet); - - talloc_free(da->packet); - da->packet = NULL; - } - - da->current_state = DATA_AGAIN; -} - -static void read_frame(struct dec_audio *da) -{ - if (da->current_frame || !da->ad_driver) - return; - - bool progress = da->ad_driver->receive_frame(da, &da->current_frame); - - da->current_state = da->current_frame ? DATA_OK : DATA_AGAIN; - if (!progress) - da->current_state = DATA_EOF; - - fix_audio_pts(da); - - bool segment_end = da->current_state == DATA_EOF; - - if (da->current_frame) { - mp_aframe_clip_timestamps(da->current_frame, da->start, da->end); - double frame_pts = mp_aframe_get_pts(da->current_frame); - if (frame_pts != MP_NOPTS_VALUE && da->start != MP_NOPTS_VALUE) - segment_end = frame_pts >= da->end; - if (mp_aframe_get_size(da->current_frame) == 0) { - talloc_free(da->current_frame); - da->current_frame = NULL; - } - } - - // If there's a new segment, start it as soon as we're drained/finished. - if (segment_end && da->new_segment) { - struct demux_packet *new_segment = da->new_segment; - da->new_segment = NULL; - - if (da->codec == new_segment->codec) { - audio_reset_decoding(da); - } else { - da->codec = new_segment->codec; - da->ad_driver->uninit(da); - da->ad_driver = NULL; - audio_init_best_codec(da); - } - - da->start = new_segment->start; - da->end = new_segment->end; - - da->packet = new_segment; - da->current_state = DATA_AGAIN; - } -} - -void audio_work(struct dec_audio *da) -{ - read_frame(da); - if (!da->current_frame) { - feed_packet(da); - if (da->current_state == DATA_WAIT) - return; - read_frame(da); // retry, to avoid redundant iterations - } -} - -// Fetch an audio frame decoded with audio_work(). Returns one of: -// DATA_OK: *out_frame is set to a new image -// DATA_WAIT: waiting for demuxer; will receive a wakeup signal -// DATA_EOF: end of file, no more frames to be expected -// DATA_AGAIN: dropped frame or something similar -int audio_get_frame(struct dec_audio *da, struct mp_aframe **out_frame) -{ - *out_frame = NULL; - if (da->current_frame) { - *out_frame = da->current_frame; - da->current_frame = NULL; - return DATA_OK; - } - if (da->current_state == DATA_OK) - return DATA_AGAIN; - return da->current_state; -} diff --git a/audio/decode/dec_audio.h b/audio/decode/dec_audio.h deleted file mode 100644 index ea504328df..0000000000 --- a/audio/decode/dec_audio.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * This file is part of mpv. - * - * mpv is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * mpv is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with mpv. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef MPLAYER_DEC_AUDIO_H -#define MPLAYER_DEC_AUDIO_H - -#include "audio/chmap.h" -#include "audio/aframe.h" -#include "demux/demux.h" -#include "demux/stheader.h" - -struct mp_decoder_list; - -struct dec_audio { - struct mp_log *log; - struct MPOpts *opts; - struct mpv_global *global; - const struct ad_functions *ad_driver; - struct sh_stream *header; - struct mp_codec_params *codec; - char *decoder_desc; - - bool try_spdif; - - struct mp_recorder_sink *recorder_sink; - - // For free use by the ad_driver - void *priv; - - // Strictly internal (dec_audio.c). - - double pts; // endpts of previous frame - double start, end; - struct demux_packet *packet; - struct demux_packet *new_segment; - struct mp_aframe *current_frame; - int current_state; -}; - -struct mp_decoder_list *audio_decoder_list(void); -int audio_init_best_codec(struct dec_audio *d_audio); -void audio_uninit(struct dec_audio *d_audio); - -void audio_work(struct dec_audio *d_audio); -int audio_get_frame(struct dec_audio *d_audio, struct mp_aframe **out_frame); - -void audio_reset_decoding(struct dec_audio *d_audio); - -// ad_spdif.c -struct mp_decoder_list *select_spdif_codec(const char *codec, const char *pref); - -#endif /* MPLAYER_DEC_AUDIO_H */ |