From 5fad0bc8a7eb78af87410c081177af914e34f972 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20=C3=96man?= Date: Wed, 14 Nov 2012 09:03:45 +0100 Subject: [PATCH] Initial work on new audio subsystem Only works on OS X right now --- Makefile | 12 +- configure.osx | 6 +- src/arch/osx/osx_app.m | 10 + src/audio/audio.c | 11 - src/audio/audio_defs.h | 2 - src/audio2/audio.c | 405 ++++++++++++++++++++++++++++++++++ src/audio2/audio.h | 60 +++++ src/audio2/mac_audio.c | 287 ++++++++++++++++++++++++ src/media.c | 6 +- src/media.h | 3 +- src/showtime.c | 3 +- src/showtime.h | 2 + src/ui/glw/glw.c | 1 + src/ui/glw/glw.h | 1 + src/ui/glw/glw_video_common.c | 4 +- support/configure.inc | 3 +- support/osx.mk | 1 + 17 files changed, 778 insertions(+), 39 deletions(-) create mode 100644 src/audio2/audio.c create mode 100644 src/audio2/audio.h create mode 100644 src/audio2/mac_audio.c diff --git a/Makefile b/Makefile index ddfbffd24b..8f41cac9fc 100644 --- a/Makefile +++ b/Makefile @@ -236,17 +236,7 @@ SRCS += src/text/fontstash.c ############################################################## # Audio subsys ############################################################## -SRCS += src/audio/audio.c \ - src/audio/audio_decoder.c \ - src/audio/audio_fifo.c \ - src/audio/audio_iec958.c \ - -SRCS-$(CONFIG_LIBASOUND) += src/audio/alsa/alsa_audio.c -SRCS-$(CONFIG_LIBPULSE) += src/audio/pulseaudio/pulseaudio.c -SRCS-$(CONFIG_LIBOGC) += src/audio/wii/wii_audio.c -SRCS-$(CONFIG_COREAUDIO) += src/audio/coreaudio/coreaudio.c -SRCS-$(CONFIG_PSL1GHT) += src/audio/ps3/ps3_audio.c -SRCS += src/audio/dummy/dummy_audio.c +SRCS += src/audio2/audio.c ############################################################## # DVD diff --git a/configure.osx b/configure.osx index b52da655ff..fa133a93b4 100755 --- a/configure.osx +++ b/configure.osx @@ -152,10 +152,8 @@ echo >>${CONFIG_MAK} "LDFLAGS_cfg += -framework OpenGL" echo >>${CONFIG_MAK} "LDFLAGS_cfg += -framework CoreVideo" echo >>${CONFIG_MAK} "LDFLAGS_cfg += -weak_framework VideoDecodeAcceleration" -# CoreAudio -if enabled coreaudio; then - echo >>${CONFIG_MAK} "LDFLAGS_cfg += -framework CoreAudio" -fi +echo >>${CONFIG_MAK} "LDFLAGS_cfg += -framework CoreAudio" +echo >>${CONFIG_MAK} "LDFLAGS_cfg += -framework AudioToolBox" # Carbon, Remote Control Wrapper uses it if enabled appleremote; then diff --git a/src/arch/osx/osx_app.m b/src/arch/osx/osx_app.m index 215fd6cfa2..5708c5c479 100644 --- a/src/arch/osx/osx_app.m +++ b/src/arch/osx/osx_app.m @@ -17,6 +17,7 @@ */ #import +#import #include #include @@ -34,6 +35,15 @@ static void mainloop_courier_init(void); +/** + * + */ +int64_t +showtime_get_avtime(void) +{ + return AudioConvertHostTimeToNanos(AudioGetCurrentHostTime()) / 1000LL; +} + /** * */ diff --git a/src/audio/audio.c b/src/audio/audio.c index d8662545dd..e806d60ea5 100644 --- a/src/audio/audio.c +++ b/src/audio/audio.c @@ -45,17 +45,6 @@ static int audio_run = 1; static hts_thread_t audio_thread_id; audio_fifo_t af0, *thefifo; - -/** - * - */ -int -audio_mode_prefer_float(void) -{ - return audio_mode_current && audio_mode_current->am_float; -} - - /** * */ diff --git a/src/audio/audio_defs.h b/src/audio/audio_defs.h index 9d4f7271fa..5da0ff9566 100644 --- a/src/audio/audio_defs.h +++ b/src/audio/audio_defs.h @@ -82,8 +82,6 @@ extern prop_t *prop_mastervol, *prop_mastermute; #define CLIP16(a) ((a) > 32767 ? 32767 : ((a) < -32768 ? -32768 : a)) -int audio_mode_prefer_float(void); - /** * Audio drivers */ diff --git a/src/audio2/audio.c b/src/audio2/audio.c new file mode 100644 index 0000000000..855fb6ec8d --- /dev/null +++ b/src/audio2/audio.c @@ -0,0 +1,405 @@ +#include +#include + +#include +#include +#include + +#include "showtime.h" +#include "media.h" +#include "audio.h" + +static audio_class_t *audio_class; + + +extern audio_class_t *mac_audio_init(void); + +static void *audio_decoder_thread(void *aux); + +/** + * + */ +void +audio_init(void) +{ + audio_class = mac_audio_init(); + + +} + + +/** + * + */ +void +audio_fini(void) +{ + +} + + +/** + * + */ +struct audio_decoder * +audio_decoder_create(struct media_pipe *mp) +{ + const audio_class_t *ac = audio_class; + + audio_decoder_t *ad = calloc(1, ac->ac_alloc_size); + ad->ad_mp = mp; + ad->ad_ac = ac; + + hts_thread_create_joinable("audio decoder", &ad->ad_tid, + audio_decoder_thread, ad, THREAD_PRIO_HIGH); + return ad; +} + + +/** + * + */ +void +audio_decoder_destroy(struct audio_decoder *ad) +{ + mp_send_cmd_head(ad->ad_mp, &ad->ad_mp->mp_audio, MB_CTRL_EXIT); + hts_thread_join(&ad->ad_tid); + free(ad); +} + + +/** + * + */ +void +audio_set_clock(media_pipe_t *mp, int64_t pts, int64_t delay, int epoch) +{ + hts_mutex_lock(&mp->mp_clock_mutex); + mp->mp_audio_clock = pts + delay; + mp->mp_audio_clock_avtime = showtime_get_avtime(); + mp->mp_audio_clock_epoch = epoch; + hts_mutex_unlock(&mp->mp_clock_mutex); +} + + + + +/** + * + */ +static void * +audio_decoder_thread(void *aux) +{ + audio_decoder_t *ad = aux; + const audio_class_t *ac = ad->ad_ac; + AVFrame *frame = avcodec_alloc_frame(); + AVPacket avpkt; + int run = 1; + media_pipe_t *mp = ad->ad_mp; + media_queue_t *mq = &mp->mp_audio; + media_buf_t *mb; + int r; + int got_frame = 0; + int64_t pts = AV_NOPTS_VALUE; + int epoch = 0; + + ad->ad_num_samples = 1024; + + if(ac->ac_init != NULL) + ac->ac_init(ad); + + hts_mutex_lock(&mp->mp_mutex); + + while(run) { + + int avail = ad->ad_avr != NULL ? avresample_available(ad->ad_avr) : 0; + + if((mb = TAILQ_FIRST(&mq->mq_q)) == NULL && avail == 0) { + hts_cond_wait(&mq->mq_avail, &mp->mp_mutex); + continue; + } + + if(mb == NULL || (mb->mb_data_type == MB_AUDIO && + avail >= ad->ad_num_samples)) { + assert(avail != 0); + assert(ad->ad_avr != NULL); + + int samples = MIN(ad->ad_num_samples, avail); + + if(ac->ac_deliver(ad, samples, pts, epoch)) { + hts_cond_wait(&mq->mq_avail, &mp->mp_mutex); + continue; + } + pts = AV_NOPTS_VALUE; + continue; + } + + + TAILQ_REMOVE(&mq->mq_q, mb, mb_link); + mq->mq_packets_current--; + mp->mp_buffer_current -= mb->mb_size; + mq_update_stats(mp, mq); + hts_cond_signal(&mp->mp_backpressure); + + hts_mutex_unlock(&mp->mp_mutex); + + switch(mb->mb_data_type) { + case MB_AUDIO: + if(mb->mb_skip || mb->mb_stream != mq->mq_stream) + break; + + if(mb->mb_cw == NULL) { + frame->sample_rate = mb->mb_rate; + frame->format = AV_SAMPLE_FMT_S16; + switch(mb->mb_channels) { + case 1: + frame->channel_layout = AV_CH_LAYOUT_MONO; + frame->nb_samples = mb->mb_size / 2; + break; + case 2: + frame->channel_layout = AV_CH_LAYOUT_STEREO; + frame->nb_samples = mb->mb_size / 4; + break; + default: + abort(); + } + frame->data[0] = mb->mb_data; + frame->linesize[0] = 0; + r = mb->mb_size; + got_frame = 1; + + } else { + + av_init_packet(&avpkt); + avpkt.data = mb->mb_data + mb->mb_offset; + avpkt.size = mb->mb_size + mb->mb_offset; + + r = avcodec_decode_audio4(mb->mb_cw->codec_ctx, frame, + &got_frame, &avpkt); + if(r < 0) + break; + } + + if(mb->mb_offset == 0 && mb->mb_pts != AV_NOPTS_VALUE) { + + int od = 0, id = 0; + + if(ad->ad_avr != NULL) { + od = avresample_available(ad->ad_avr) * + 1000000LL / ad->ad_out_sample_rate; + id = avresample_get_delay(ad->ad_avr) * + 1000000LL / frame->sample_rate; + } + + pts = mb->mb_pts - od - id; + epoch = mb->mb_epoch; + + if(mb->mb_drive_clock) + mp_set_current_time(mp, mb->mb_pts - ad->ad_delay, + mb->mb_epoch, mb->mb_delta); + } + + mb->mb_offset += r; + + if(got_frame) { + + if(frame->sample_rate != ad->ad_in_sample_rate || + frame->format != ad->ad_in_sample_format || + frame->channel_layout != ad->ad_in_channel_layout) { + + ad->ad_in_sample_rate = frame->sample_rate; + ad->ad_in_sample_format = frame->format; + ad->ad_in_channel_layout = frame->channel_layout; + + ac->ac_reconfig(ad); + + if(ad->ad_avr == NULL) + ad->ad_avr = avresample_alloc_context(); + else + avresample_close(ad->ad_avr); + + av_opt_set_int(ad->ad_avr, "in_sample_fmt", + ad->ad_in_sample_format, 0); + av_opt_set_int(ad->ad_avr, "in_sample_rate", + ad->ad_in_sample_rate, 0); + av_opt_set_int(ad->ad_avr, "in_channel_layout", + ad->ad_in_channel_layout, 0); + + av_opt_set_int(ad->ad_avr, "out_sample_fmt", + ad->ad_out_sample_format, 0); + av_opt_set_int(ad->ad_avr, "out_sample_rate", + ad->ad_out_sample_rate, 0); + av_opt_set_int(ad->ad_avr, "out_channel_layout", + ad->ad_out_channel_layout, 0); + + char buf1[128]; + char buf2[128]; + + av_get_channel_layout_string(buf1, sizeof(buf1), + -1, ad->ad_in_channel_layout); + av_get_channel_layout_string(buf2, sizeof(buf2), + -1, ad->ad_out_channel_layout); + + TRACE(TRACE_DEBUG, "Audio", + "Converting from [%s %dHz %s] to [%s %dHz %s]", + buf1, ad->ad_in_sample_rate, + av_get_sample_fmt_name(ad->ad_in_sample_format), + buf2, ad->ad_out_sample_rate, + av_get_sample_fmt_name(ad->ad_out_sample_format)); + + if(avresample_open(ad->ad_avr)) { + TRACE(TRACE_ERROR, "AudioQueue", "Unable to open resampler"); + avresample_free(&ad->ad_avr); + } + } + if(ad->ad_avr != NULL) + avresample_convert(ad->ad_avr, NULL, 0, 0, + frame->data, frame->linesize[0], + frame->nb_samples); + } + + if(mb->mb_offset < mb->mb_size) { + hts_mutex_lock(&mp->mp_mutex); + TAILQ_INSERT_HEAD(&mq->mq_q, mb, mb_link); + mq->mq_packets_current++; + mp->mp_buffer_current += mb->mb_size; + continue; + } + break; + + case MB_CTRL_PAUSE: + ac->ac_pause(ad); + break; + + case MB_CTRL_PLAY: + ac->ac_play(ad); + break; + + case MB_FLUSH: + ac->ac_flush(ad); + pts = AV_NOPTS_VALUE; + break; + + case MB_CTRL_EXIT: + run = 0; + break; + + default: + abort(); + } + + hts_mutex_lock(&mp->mp_mutex); + media_buf_free_locked(mp, mb); + } + + hts_mutex_unlock(&mp->mp_mutex); + + ac->ac_fini(ad); + + avcodec_free_frame(&frame); + + if(ad->ad_avr != NULL) { + avresample_close(ad->ad_avr); + avresample_free(&ad->ad_avr); + } + return NULL; +} + + + + +#if 0 +/** + * + */ +static void * +dummy_audio_thread(void *aux) +{ + audio_decoder_t *ad = aux; + media_pipe_t *mp = ad->ad_mp; + media_queue_t *mq = &mp->mp_audio; + media_buf_t *mb; + int hold = 0; + int run = 1; + int64_t rt = 0; + int64_t base = AV_NOPTS_VALUE; + + + hts_mutex_lock(&mp->mp_mutex); + + while(run) { + + if((mb = TAILQ_FIRST(&mq->mq_q)) == NULL) { + hts_cond_wait(&mq->mq_avail, &mp->mp_mutex); + continue; + } + + if(mb->mb_data_type == MB_AUDIO && hold && mb->mb_skip == 0) { + hts_cond_wait(&mq->mq_avail, &mp->mp_mutex); + continue; + } + + TAILQ_REMOVE(&mq->mq_q, mb, mb_link); + mq->mq_packets_current--; + mp->mp_buffer_current -= mb->mb_size; + mq_update_stats(mp, mq); + hts_cond_signal(&mp->mp_backpressure); + hts_mutex_unlock(&mp->mp_mutex); + + switch(mb->mb_data_type) { + case MB_CTRL_EXIT: + run = 0; + break; + + case MB_CTRL_PAUSE: + hold = 1; + break; + + case MB_CTRL_PLAY: + hold = 0; + base = AV_NOPTS_VALUE; + break; + + case MB_FLUSH: + base = AV_NOPTS_VALUE; + break; + + case MB_AUDIO: + if(mb->mb_skip || mb->mb_stream != mq->mq_stream) + break; + if(mb->mb_pts != AV_NOPTS_VALUE) { + audio_set_clock(mp, mb->mb_pts, 0, mb->mb_epoch); + + if(base == AV_NOPTS_VALUE) { + base = mb->mb_pts; + rt = showtime_get_ts(); + } else { + int64_t d = mb->mb_pts - base; + if(d > 0) { + int sleeptime = rt + d - showtime_get_ts(); + if(sleeptime > 0) + usleep(sleeptime); + } + } + } + break; + + default: + abort(); + } + hts_mutex_lock(&mp->mp_mutex); + media_buf_free_locked(mp, mb); + } + hts_mutex_unlock(&mp->mp_mutex); + return NULL; +} + + +/** + * + */ +static audio_class_t dummy_audio_class = { + .ac_alloc_size = sizeof(audio_decoder_t), + .ac_thread = dummy_audio_thread, +}; +#endif diff --git a/src/audio2/audio.h b/src/audio2/audio.h new file mode 100644 index 0000000000..dadb0f7811 --- /dev/null +++ b/src/audio2/audio.h @@ -0,0 +1,60 @@ +#pragma once + +#include +#include + +#include "arch/threads.h" + +struct media_pipe; +struct audio_decoder; + +typedef struct audio_class { + size_t ac_alloc_size; + int (*ac_init)(struct audio_decoder *ad); + void (*ac_fini)(struct audio_decoder *ad); + int (*ac_reconfig)(struct audio_decoder *ad); + int (*ac_deliver)(struct audio_decoder *ad, int samples, + int64_t pts, int epoch); + + void (*ac_pause)(struct audio_decoder *ad); + void (*ac_play)(struct audio_decoder *ad); + void (*ac_flush)(struct audio_decoder *ad); + +} audio_class_t; + + +typedef struct audio_decoder { + const audio_class_t *ad_ac; + struct media_pipe *ad_mp; + hts_thread_t ad_tid; + + int ad_num_samples; // Max number of samples to be delivered per round + int ad_delay; // Audio output delay in us + + int ad_in_sample_rate; + enum AVSampleFormat ad_in_sample_format; + int64_t ad_in_channel_layout; + + int ad_out_sample_rate; + enum AVSampleFormat ad_out_sample_format; + int64_t ad_out_channel_layout; + + AVAudioResampleContext *ad_avr; + +} audio_decoder_t; + + +void audio_init(void); + +void audio_fini(void); + +audio_decoder_t *audio_decoder_create(struct media_pipe *mp); + +void audio_decoder_destroy(audio_decoder_t *ad); + +void audio_set_clock(struct media_pipe *mp, int64_t pts, int64_t delay, + int epoch); + +struct AVFrame; + +int audio_decoder_configure(audio_decoder_t *ad, const struct AVFrame *avf); diff --git a/src/audio2/mac_audio.c b/src/audio2/mac_audio.c new file mode 100644 index 0000000000..47b88d414a --- /dev/null +++ b/src/audio2/mac_audio.c @@ -0,0 +1,287 @@ +#include +#include +#include + +#include "showtime.h" +#include "audio.h" +#include "media.h" + +#define NUM_BUFS 1000 + +typedef struct decoder { + audio_decoder_t ad; + AudioQueueRef aq; + int framesize; + struct { + AudioQueueBufferRef buf; + int avail; + int size; + } buffers[NUM_BUFS]; +} decoder_t; + + +/** + * + */ +static void +return_buf(void *aux, AudioQueueRef aq, AudioQueueBufferRef buf) +{ + decoder_t *d = aux; + media_pipe_t *mp = d->ad.ad_mp; + int i; + hts_mutex_lock(&mp->mp_mutex); + for(i = 0; i < NUM_BUFS; i++) { + if(d->buffers[i].buf == buf) { + d->buffers[i].avail = 1; + hts_cond_signal(&mp->mp_audio.mq_avail); + hts_mutex_unlock(&mp->mp_mutex); + return; + } + } + abort(); +} + + +/** + * + */ +static AudioQueueBufferRef +allocbuf(decoder_t *d, int pos, int bytes) +{ + d->buffers[pos].size = bytes; + AudioQueueAllocateBuffer(d->aq, bytes, &d->buffers[pos].buf); + d->buffers[pos].avail = 0; + return d->buffers[pos].buf; +} + + +/** + * + */ +static AudioQueueBufferRef +getbuf(decoder_t *d, int bytes) +{ + int i; + assert(d->aq != NULL); + for(i = 0; i < NUM_BUFS; i++) { + if(d->buffers[i].avail && d->buffers[i].size >= bytes) { + d->buffers[i].avail = 0; + return d->buffers[i].buf; + } + } + + for(i = 0; i < NUM_BUFS; i++) + if(d->buffers[i].buf == NULL) + return allocbuf(d, i, bytes); + + for(i = 0; i < NUM_BUFS; i++) + if(d->buffers[i].avail) { + AudioQueueFreeBuffer(d->aq, d->buffers[i].buf); + return allocbuf(d, i, bytes); + } + return NULL; +} + + +/** + * + */ +static void +mac_audio_fini(audio_decoder_t *ad) +{ + decoder_t *d = (decoder_t *)ad; + if(d->aq) + AudioQueueDispose(d->aq, true); +} + + +/** + * + */ +static int +mac_audio_reconfig(audio_decoder_t *ad) +{ + decoder_t *d = (decoder_t *)ad; + int i; + OSStatus r; + + if(d->aq) { + AudioQueueDispose(d->aq, false); + d->aq = NULL; + + for(i = 0; i < NUM_BUFS; i++) { + d->buffers[i].buf = NULL; + d->buffers[i].avail = 0; + d->buffers[i].size = 0; + } + } + + AudioStreamBasicDescription desc = {0}; + + // Coding + + desc.mFormatID = kAudioFormatLinearPCM; + + // Rate + + ad->ad_out_sample_rate = ad->ad_in_sample_rate; + desc.mSampleRate = ad->ad_out_sample_rate; + + // Channel configuration + + ad->ad_out_channel_layout = AV_CH_LAYOUT_STEREO; + desc.mChannelsPerFrame = 2; + + // Sample format + int sample_size; + + switch(ad->ad_in_sample_format) { + case AV_SAMPLE_FMT_S32: + case AV_SAMPLE_FMT_S32P: + ad->ad_out_sample_format = AV_SAMPLE_FMT_S32; + desc.mFormatFlags = kAudioFormatFlagIsSignedInteger; + sample_size = sizeof(int32_t); + break; + + case AV_SAMPLE_FMT_S16: + case AV_SAMPLE_FMT_S16P: + if(ad->ad_in_channel_layout == AV_CH_LAYOUT_STEREO) { + ad->ad_out_sample_format = AV_SAMPLE_FMT_S16; + desc.mFormatFlags = kAudioFormatFlagIsSignedInteger; + sample_size = sizeof(int16_t); + break; + } + // FALLTHRU + default: + ad->ad_out_sample_format = AV_SAMPLE_FMT_FLT; + desc.mFormatFlags = kAudioFormatFlagIsFloat; + sample_size = sizeof(float); + break; + } + + desc.mBytesPerFrame = desc.mChannelsPerFrame * sample_size; + desc.mBitsPerChannel = 8 * sample_size; + desc.mFramesPerPacket = 1; + desc.mBytesPerPacket = desc.mBytesPerFrame; + + d->framesize = desc.mBytesPerFrame; + + TRACE(TRACE_DEBUG, "AudioQueue", "Init %d Hz", ad->ad_out_sample_rate); + + r = AudioQueueNewOutput(&desc, return_buf, d, CFRunLoopGetMain(), + kCFRunLoopCommonModes, 0, &d->aq); + if(r) { + d->aq = NULL; + TRACE(TRACE_ERROR, "AudioQueue", "AudioQueueNewOutput() error %d", r); + return 1; + } + + r = AudioQueueStart(d->aq, NULL); + if(r) { + TRACE(TRACE_ERROR, "AudioQueue", "AudioQueueStart() error %d", r); + AudioQueueDispose(d->aq, false); + d->aq = NULL; + return 1; + } + return 0; +} + + +/** + * + */ +static void +mac_audio_pause(audio_decoder_t *ad) +{ + decoder_t *d = (decoder_t *)ad; + if(d->aq) + AudioQueuePause(d->aq); +} + + +/** + * + */ +static void +mac_audio_play(audio_decoder_t *ad) +{ + decoder_t *d = (decoder_t *)ad; + if(d->aq) + AudioQueueStart(d->aq, NULL); +} + + +/** + * + */ +static void +mac_audio_flush(audio_decoder_t *ad) +{ + decoder_t *d = (decoder_t *)ad; + if(d->aq) + AudioQueueReset(d->aq); +} + + +/** + * + */ +static int +mac_audio_deliver(audio_decoder_t *ad, int samples, + int64_t pts, int epoch) +{ + decoder_t *d = (decoder_t *)ad; + int bytes = samples * d->framesize; + + AudioQueueBufferRef b = getbuf(d, bytes); + if(b == NULL) + return 1; + + uint8_t *data[8] = {0}; + data[0] = (uint8_t *)b->mAudioData; + avresample_read(ad->ad_avr, data, samples); + b->mAudioDataByteSize = bytes; + + AudioTimeStamp ats; + AudioQueueEnqueueBufferWithParameters(d->aq, b, 0, NULL, + 0, 0, 0, NULL, NULL, &ats); + + if(ats.mFlags & kAudioTimeStampHostTimeValid && + pts != AV_NOPTS_VALUE) { + int64_t t = AudioConvertHostTimeToNanos(ats.mHostTime) / 1000LL; + ad->ad_delay = t - showtime_get_avtime(); + + media_pipe_t *mp = ad->ad_mp; + + hts_mutex_lock(&mp->mp_clock_mutex); + mp->mp_audio_clock_avtime = t; + mp->mp_audio_clock_epoch = epoch; + mp->mp_audio_clock = pts; + hts_mutex_unlock(&mp->mp_clock_mutex); + } + return 0; +} + +/** + * + */ +static audio_class_t mac_audio_class = { + .ac_alloc_size = sizeof(decoder_t), + + .ac_fini = mac_audio_fini, + .ac_reconfig = mac_audio_reconfig, + .ac_deliver = mac_audio_deliver, + + .ac_pause = mac_audio_pause, + .ac_play = mac_audio_play, + .ac_flush = mac_audio_flush, +}; + +audio_class_t *mac_audio_init(void); + +audio_class_t * +mac_audio_init(void) +{ + return &mac_audio_class; +} + diff --git a/src/media.c b/src/media.c index c21b3c28fe..eba9517291 100644 --- a/src/media.c +++ b/src/media.c @@ -28,8 +28,7 @@ #include "media.h" #include "showtime.h" -#include "audio/audio_decoder.h" -#include "audio/audio_defs.h" +#include "audio2/audio.h" #include "event.h" #include "playqueue.h" #include "fileaccess/fa_libav.h" @@ -1246,9 +1245,6 @@ media_codec_create_lavc(media_codec_t *cw, enum CodecID id, cw->codec_ctx->flags2 |= CODEC_FLAG2_FAST; } - if(audio_mode_prefer_float() && cw->codec->id != CODEC_ID_AAC) - cw->codec_ctx->request_sample_fmt = AV_SAMPLE_FMT_FLT; - if(avcodec_open2(cw->codec_ctx, cw->codec, NULL) < 0) { if(ctx == NULL) free(cw->codec_ctx); diff --git a/src/media.h b/src/media.h index dc56e8ca20..41ac149505 100644 --- a/src/media.h +++ b/src/media.h @@ -126,6 +126,7 @@ typedef struct media_buf { void (*mb_dtor)(struct media_buf *mb); int mb_size; + int mb_offset; union { int32_t mb_data32; @@ -245,7 +246,7 @@ typedef struct media_pipe { hts_mutex_t mp_clock_mutex; int64_t mp_audio_clock; - int64_t mp_audio_clock_realtime; + int64_t mp_audio_clock_avtime; int mp_audio_clock_epoch; int mp_avdelta; // Audio vs video delta (µs) int mp_svdelta; // Subtitle vs video delta (µs) diff --git a/src/showtime.c b/src/showtime.c index d820d5c0f8..4c0f7f3415 100644 --- a/src/showtime.c +++ b/src/showtime.c @@ -34,7 +34,8 @@ #include "prop/prop.h" #include "arch/arch.h" -#include "audio/audio_defs.h" +#include "media.h" +#include "audio2/audio.h" #include "backend/backend.h" #include "navigator.h" #include "settings.h" diff --git a/src/showtime.h b/src/showtime.h index c666d86c5a..56a5068840 100644 --- a/src/showtime.h +++ b/src/showtime.h @@ -83,6 +83,8 @@ uint32_t showtime_parse_version_int(const char *str); extern int64_t showtime_get_ts(void); +extern int64_t showtime_get_avtime(void); + extern const char *showtime_get_system_type(void); extern uint64_t arch_get_seed(void); diff --git a/src/ui/glw/glw.c b/src/ui/glw/glw.c index 27e53913c2..44ecf91c9f 100644 --- a/src/ui/glw/glw.c +++ b/src/ui/glw/glw.c @@ -549,6 +549,7 @@ glw_prepare_frame(glw_root_t *gr, int flags) } gr->gr_frame_start = showtime_get_ts(); + gr->gr_frame_start_avtime = showtime_get_avtime(); gr->gr_time = (gr->gr_frame_start - gr->gr_ui_start) / 1000000.0; if(!(flags & GLW_NO_FRAMERATE_UPDATE)) { diff --git a/src/ui/glw/glw.h b/src/ui/glw/glw.h index 9308ad4b2b..3f37580b45 100644 --- a/src/ui/glw/glw.h +++ b/src/ui/glw/glw.h @@ -680,6 +680,7 @@ typedef struct glw_root { struct glw_video_list gr_video_decoders; int64_t gr_ui_start; // Timestamp UI was initialized int64_t gr_frame_start; // Timestamp when we started rendering frame + int64_t gr_frame_start_avtime; // AVtime when start rendering frame int64_t gr_hz_sample; prop_t *gr_is_fullscreen; // Set if our window is in fullscreen diff --git a/src/ui/glw/glw_video_common.c b/src/ui/glw/glw_video_common.c index 9f04892779..1c40d77fdb 100644 --- a/src/ui/glw/glw_video_common.c +++ b/src/ui/glw/glw_video_common.c @@ -190,8 +190,8 @@ glw_video_compute_avdiff(glw_root_t *gr, video_decoder_t *vd, media_pipe_t *mp, hts_mutex_lock(&mp->mp_clock_mutex); - aclock = mp->mp_audio_clock + gr->gr_frame_start - - mp->mp_audio_clock_realtime; + aclock = mp->mp_audio_clock + gr->gr_frame_start_avtime + - mp->mp_audio_clock_avtime; hts_mutex_unlock(&mp->mp_clock_mutex); diff --git a/support/configure.inc b/support/configure.inc index 6117639885..d0d0845dee 100644 --- a/support/configure.inc +++ b/support/configure.inc @@ -45,7 +45,6 @@ CONFIG_LIST=" lirc stdin release - coreaudio avahi appleremote bonjour @@ -368,7 +367,7 @@ finalize() { if enabled libav; then echo >>${CONFIG_MAK} "CFLAGS_cfg += -I${LIBAV_PATH}/include" - echo >>${CONFIG_MAK} "LDFLAGS_cfg += -L${LIBAV_PATH}/lib -lswscale -lavformat -lavcodec -lavutil" + echo >>${CONFIG_MAK} "LDFLAGS_cfg += -L${LIBAV_PATH}/lib -lavresample -lswscale -lavformat -lavcodec -lavutil" fi if enabled polarssl; then diff --git a/support/osx.mk b/support/osx.mk index 10a1f3ed66..870efe6183 100644 --- a/support/osx.mk +++ b/support/osx.mk @@ -8,6 +8,7 @@ SRCS += src/arch/osx/osx_app.m \ src/arch/posix/posix.c \ src/arch/posix/posix_threads.c \ src/networking/net_posix.c \ + src/audio2/mac_audio.c \ DVDCSS_CFLAGS = -DDARWIN_DVD_IOCTL -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE