mirror of
https://github.com/mpv-player/mpv
synced 2025-03-02 20:28:02 +00:00
ao_lavc.c accesses ao->buffer, which I consider internal. The access was done in ao_lavc.c/uninit(), which tried to get the left-over audio in order to write the last (possibly partial) audio frame. The play() function didn't accept partial frames, because the AOPLAY_FINAL_CHUNK flag was not correctly set, and handling it otherwise would require an internal FIFO. Fix this by making sure that with gapless audio (used with encoding), the AOPLAY_FINAL_CHUNK is set only once, instead when each file ends. Basically, move the hack in ao_lavc's uninit to uninit_player. One thing can not be entirely correctly handled: if gapless audio is active, we don't know really whether the AO is closed because the file ended playing (i.e. we want to send the buffered remainder of the audio to the AO), or whether the user is quitting the player. (The stop_play flag is overwritten, fixing that is perhaps not worth it.) Handle this by adding additional code to drain the AO and the buffers when playback is quit (see play_current_file() change). Test case: mpv avdevice://lavfi:sine=441 avdevice://lavfi:sine=441 -length 0.2267 -gapless-audio
110 lines
3.7 KiB
C
110 lines
3.7 KiB
C
/*
|
|
* This file is part of MPlayer.
|
|
*
|
|
* MPlayer is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* MPlayer 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 General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along
|
|
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
*/
|
|
|
|
#ifndef MPLAYER_AUDIO_OUT_H
|
|
#define MPLAYER_AUDIO_OUT_H
|
|
|
|
#include <stdbool.h>
|
|
|
|
#include "mpvcore/bstr.h"
|
|
#include "mpvcore/mp_common.h"
|
|
#include "audio/chmap.h"
|
|
#include "audio/chmap_sel.h"
|
|
|
|
enum aocontrol {
|
|
// _VOLUME commands take struct ao_control_vol pointer for input/output.
|
|
// If there's only one volume, SET should use average of left/right.
|
|
AOCONTROL_GET_VOLUME,
|
|
AOCONTROL_SET_VOLUME,
|
|
// _MUTE commands take a pointer to bool
|
|
AOCONTROL_GET_MUTE,
|
|
AOCONTROL_SET_MUTE,
|
|
};
|
|
|
|
#define AOPLAY_FINAL_CHUNK 1
|
|
|
|
typedef struct ao_control_vol {
|
|
float left;
|
|
float right;
|
|
} ao_control_vol_t;
|
|
|
|
struct ao;
|
|
|
|
struct ao_driver {
|
|
bool encode;
|
|
const char *name;
|
|
const char *description;
|
|
int (*control)(struct ao *ao, enum aocontrol cmd, void *arg);
|
|
int (*init)(struct ao *ao);
|
|
void (*uninit)(struct ao *ao, bool cut_audio);
|
|
void (*reset)(struct ao*ao);
|
|
int (*get_space)(struct ao *ao);
|
|
int (*play)(struct ao *ao, void *data, int len, int flags);
|
|
float (*get_delay)(struct ao *ao);
|
|
void (*pause)(struct ao *ao);
|
|
void (*resume)(struct ao *ao);
|
|
|
|
// For option parsing (see vo.h)
|
|
int priv_size;
|
|
const void *priv_defaults;
|
|
const struct m_option *options;
|
|
};
|
|
|
|
/* global data used by mplayer and plugins */
|
|
struct ao {
|
|
int samplerate;
|
|
struct mp_chmap channels;
|
|
int format;
|
|
int bps; // bytes per second
|
|
double pts; // some mplayer.c state (why is this here?)
|
|
struct bstr buffer;
|
|
int buffer_playable_size; // part of the part of the buffer the AO hasn't
|
|
// accepted yet with play()
|
|
bool probing; // if true, don't fail loudly on init
|
|
bool untimed;
|
|
bool no_persistent_volume; // the AO does the equivalent of af_volume
|
|
bool per_application_mixer; // like above, but volume persists (per app)
|
|
const struct ao_driver *driver;
|
|
void *priv;
|
|
struct encode_lavc_context *encode_lavc_ctx;
|
|
struct MPOpts *opts;
|
|
struct input_ctx *input_ctx;
|
|
struct mp_log *log; // Using e.g. "[ao/coreaudio]" as prefix
|
|
};
|
|
|
|
struct mpv_global;
|
|
struct ao *ao_init_best(struct mpv_global *global,
|
|
struct input_ctx *input_ctx,
|
|
struct encode_lavc_context *encode_lavc_ctx,
|
|
int samplerate, int format, struct mp_chmap channels);
|
|
void ao_uninit(struct ao *ao, bool cut_audio);
|
|
int ao_play(struct ao *ao, void *data, int len, int flags);
|
|
int ao_control(struct ao *ao, enum aocontrol cmd, void *arg);
|
|
double ao_get_delay(struct ao *ao);
|
|
int ao_get_space(struct ao *ao);
|
|
void ao_reset(struct ao *ao);
|
|
void ao_pause(struct ao *ao);
|
|
void ao_resume(struct ao *ao);
|
|
|
|
bool ao_chmap_sel_adjust(struct ao *ao, const struct mp_chmap_sel *s,
|
|
struct mp_chmap *map);
|
|
bool ao_chmap_sel_get_def(struct ao *ao, const struct mp_chmap_sel *s,
|
|
struct mp_chmap *map, int num);
|
|
|
|
#endif /* MPLAYER_AUDIO_OUT_H */
|