Use audio callback
The libretro frontend now controls audio, and can now therefore pause
the video and audio.
This requires a modified version of libmpv which is not currently
upstream: 789aa4528e
Not that all audio is currently converted to 48000Hz.
Squashed commit of the following:
commit ef16a4045e36cb9acd87ef2632d57f7380494781
Author: Mahyar Koshkouei <mahyar.koshkouei@gmail.com>
Date: Mon Feb 12 22:29:52 2018 +0000
Working audio-cb
Audio currently resampled to 48kHz.
Signed-off-by: Mahyar Koshkouei <mahyar.koshkouei@gmail.com>
commit 0b430219b8cae47af4f0f32611f888d51c3393b1
Author: Mahyar Koshkouei <mahyar.koshkouei@gmail.com>
Date: Mon Feb 12 19:23:38 2018 +0000
Minor audio-cb changes for testing
Signed-off-by: Mahyar Koshkouei <mahyar.koshkouei@gmail.com>
commit 65a2ebe354066839bd8e27584684c901709a1c2b
Author: Mahyar Koshkouei <mahyar.koshkouei@gmail.com>
Date: Mon Feb 12 16:51:53 2018 +0000
WIP: use mpv audio-cb output
Audio quality and timing is poor.
Signed-off-by: Mahyar Koshkouei <mahyar.koshkouei@gmail.com>
commit ce22b385461c087217542b2a4c1e0f01ea530164
Author: Mahyar Koshkouei <mahyar.koshkouei@gmail.com>
Date: Mon Feb 12 10:22:53 2018 +0000
Remove spaces
Signed-off-by: Mahyar Koshkouei <mahyar.koshkouei@gmail.com>
Signed-off-by: Mahyar Koshkouei <mahyar.koshkouei@gmail.com>
This commit is contained in:
parent
2cea3d17b5
commit
4e359318c4
|
@ -2222,6 +2222,7 @@ typedef void (RETRO_CALLCONV *retro_audio_sample_t)(int16_t left, int16_t right)
|
||||||
* One frame is defined as a sample of left and right channels, interleaved.
|
* One frame is defined as a sample of left and right channels, interleaved.
|
||||||
* I.e. int16_t buf[4] = { l, r, l, r }; would be 2 frames.
|
* I.e. int16_t buf[4] = { l, r, l, r }; would be 2 frames.
|
||||||
* Only one of the audio callbacks must ever be used.
|
* Only one of the audio callbacks must ever be used.
|
||||||
|
* Limited to a maximum of 1024 samples.
|
||||||
*/
|
*/
|
||||||
typedef size_t (RETRO_CALLCONV *retro_audio_sample_batch_t)(const int16_t *data,
|
typedef size_t (RETRO_CALLCONV *retro_audio_sample_batch_t)(const int16_t *data,
|
||||||
size_t frames);
|
size_t frames);
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
/* mpv media player libretro core
|
/* mpv media player libretro core
|
||||||
* Copyright (C) 2018 Mahyar Koshkouei
|
* Copyright (C) 2018 Mahyar Koshkouei
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
@ -56,6 +56,13 @@ static int64_t *playback_time = 0;
|
||||||
/* filepath required globaly as mpv is reopened on context change */
|
/* filepath required globaly as mpv is reopened on context change */
|
||||||
static char *filepath = NULL;
|
static char *filepath = NULL;
|
||||||
|
|
||||||
|
static volatile int frame_queue = 0;
|
||||||
|
|
||||||
|
void queue_new_frame(void *cb_ctx)
|
||||||
|
{
|
||||||
|
frame_queue++;
|
||||||
|
}
|
||||||
|
|
||||||
static void fallback_log(enum retro_log_level level, const char *fmt, ...)
|
static void fallback_log(enum retro_log_level level, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
(void)level;
|
(void)level;
|
||||||
|
@ -193,7 +200,7 @@ void retro_get_system_info(struct retro_system_info *info)
|
||||||
|
|
||||||
void retro_get_system_av_info(struct retro_system_av_info *info)
|
void retro_get_system_av_info(struct retro_system_av_info *info)
|
||||||
{
|
{
|
||||||
float sampling_rate = 48000.0f;
|
float sampling_rate = 44100.0f;
|
||||||
|
|
||||||
struct retro_variable var = { .key = "test_aspect" };
|
struct retro_variable var = { .key = "test_aspect" };
|
||||||
environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var);
|
environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var);
|
||||||
|
@ -294,6 +301,10 @@ static void context_reset(void)
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mpv_opengl_cb_set_update_callback(mpv_gl, queue_new_frame, NULL);
|
||||||
|
|
||||||
|
mpv_set_option_string(mpv, "ao", "audio-cb");
|
||||||
|
|
||||||
if(mpv_set_option_string(mpv, "hwdec", "auto") < 0)
|
if(mpv_set_option_string(mpv, "hwdec", "auto") < 0)
|
||||||
log_cb(RETRO_LOG_ERROR, "failed to set hwdec option\n");
|
log_cb(RETRO_LOG_ERROR, "failed to set hwdec option\n");
|
||||||
|
|
||||||
|
@ -317,6 +328,11 @@ static void context_reset(void)
|
||||||
usleep(10);
|
usleep(10);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* TODO #2: Check for the highest samplerate in audio stream, and use that.
|
||||||
|
* Fall back to 48kHz otherwise.
|
||||||
|
*/
|
||||||
|
mpv_set_option_string(mpv, "audio-samplerate", "48000");
|
||||||
|
|
||||||
log_cb(RETRO_LOG_INFO, "Context reset.\n");
|
log_cb(RETRO_LOG_INFO, "Context reset.\n");
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
@ -381,20 +397,25 @@ void retro_reset(void)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
static void audio_callback(void)
|
static void audio_callback(void)
|
||||||
{
|
{
|
||||||
static unsigned phase;
|
/* Obtain len samples to reduce lag. */
|
||||||
|
int len = 2*1024;
|
||||||
|
static int16_t frames[512];
|
||||||
|
|
||||||
for (unsigned i = 0; i < 30000 / 60; i++, phase++)
|
while(len > 0)
|
||||||
{
|
{
|
||||||
int16_t val = 0x800 * sinf(2.0f * M_PI * phase * 300.0f / 30000.0f);
|
int mpv_len = mpv_audio_callback(&frames, len > 512 ? 512*2 : len*2);
|
||||||
audio_cb(val, val);
|
//printf("mpv cb: %d\n", mpv_len);
|
||||||
}
|
if(mpv_len < 1)
|
||||||
|
return;
|
||||||
|
|
||||||
phase %= 100;
|
len -= mpv_len;
|
||||||
|
|
||||||
|
//printf("acb: %lu\n", audio_batch_cb(frames, mpv_len));
|
||||||
|
audio_batch_cb(frames, mpv_len);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
static void retropad_update_input(void)
|
static void retropad_update_input(void)
|
||||||
{
|
{
|
||||||
|
@ -414,7 +435,7 @@ static void retropad_update_input(void)
|
||||||
/* A ternary operator is used since input_state_cb returns an int16_t, but
|
/* A ternary operator is used since input_state_cb returns an int16_t, but
|
||||||
* we only care about whether the button is on or off which is why we store
|
* we only care about whether the button is on or off which is why we store
|
||||||
* the value in a single bit for each button.
|
* the value in a single bit for each button.
|
||||||
*
|
*
|
||||||
* Unsure if saving the memory is worth the extra checks, costing CPU time,
|
* Unsure if saving the memory is worth the extra checks, costing CPU time,
|
||||||
* but both are incredibly miniscule anyway.
|
* but both are incredibly miniscule anyway.
|
||||||
*/
|
*/
|
||||||
|
@ -471,7 +492,7 @@ void retro_run(void)
|
||||||
* retro_get_system_av_info() call.
|
* retro_get_system_av_info() call.
|
||||||
*/
|
*/
|
||||||
static bool updated_video_dimensions = false;
|
static bool updated_video_dimensions = false;
|
||||||
static int64_t width, height;
|
static int64_t width = 0, height = 0;
|
||||||
|
|
||||||
if(updated_video_dimensions == false)
|
if(updated_video_dimensions == false)
|
||||||
{
|
{
|
||||||
|
@ -493,18 +514,37 @@ void retro_run(void)
|
||||||
.aspect_ratio = -1,
|
.aspect_ratio = -1,
|
||||||
};
|
};
|
||||||
|
|
||||||
environ_cb(RETRO_ENVIRONMENT_SET_SYSTEM_AV_INFO, &geometry);
|
struct retro_system_timing timing = {
|
||||||
|
.fps = 60.0f,
|
||||||
|
.sample_rate = 48000.0f,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct retro_system_av_info av_info = {
|
||||||
|
.geometry = geometry,
|
||||||
|
.timing = timing,
|
||||||
|
};
|
||||||
|
|
||||||
|
if(width > 0 && height > 0)
|
||||||
|
environ_cb(RETRO_ENVIRONMENT_SET_SYSTEM_AV_INFO, &av_info);
|
||||||
|
|
||||||
updated_video_dimensions = true;
|
updated_video_dimensions = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
print_mpv_logs();
|
print_mpv_logs();
|
||||||
|
|
||||||
retropad_update_input();
|
retropad_update_input();
|
||||||
/* TODO #2: Implement an audio callback feature in to libmpv */
|
|
||||||
/* audio_callback(); */
|
|
||||||
|
|
||||||
mpv_opengl_cb_draw(mpv_gl, hw_render.get_current_framebuffer(), width, height);
|
if(frame_queue > 0)
|
||||||
video_cb(RETRO_HW_FRAME_BUFFER_VALID, width, height, 0);
|
{
|
||||||
|
mpv_opengl_cb_draw(mpv_gl, hw_render.get_current_framebuffer(), width, height);
|
||||||
|
video_cb(RETRO_HW_FRAME_BUFFER_VALID, width, height, 0);
|
||||||
|
frame_queue--;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
video_cb(NULL, width, height, 0);
|
||||||
|
|
||||||
|
/* TODO #2: Implement an audio callback feature in to libmpv */
|
||||||
|
audio_callback();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue