comparison libao2/ao_macosx.c @ 29201:06e7728c5b34

Use libavutil/fifo.h for macosx ao instead of its own FIFO implementation.
author reimar
date Sun, 03 May 2009 20:57:37 +0000
parents 9a5b8c2ed6de
children
comparison
equal deleted inserted replaced
29200:80492f643e9b 29201:06e7728c5b34
50 50
51 #include "audio_out.h" 51 #include "audio_out.h"
52 #include "audio_out_internal.h" 52 #include "audio_out_internal.h"
53 #include "libaf/af_format.h" 53 #include "libaf/af_format.h"
54 #include "osdep/timer.h" 54 #include "osdep/timer.h"
55 #include "libavutil/fifo.h"
55 56
56 static const ao_info_t info = 57 static const ao_info_t info =
57 { 58 {
58 "Darwin/Mac OS X native audio output", 59 "Darwin/Mac OS X native audio output",
59 "macosx", 60 "macosx",
89 /* Original common part */ 90 /* Original common part */
90 int packetSize; 91 int packetSize;
91 int paused; 92 int paused;
92 93
93 /* Ring-buffer */ 94 /* Ring-buffer */
94 /* does not need explicit synchronization, but needs to allocate 95 AVFifoBuffer *buffer;
95 * (num_chunks + 1) * chunk_size memory to store num_chunks * chunk_size 96 unsigned int buffer_len; ///< must always be num_chunks * chunk_size
96 * data */
97 unsigned char *buffer;
98 unsigned int buffer_len; ///< must always be (num_chunks + 1) * chunk_size
99 unsigned int num_chunks; 97 unsigned int num_chunks;
100 unsigned int chunk_size; 98 unsigned int chunk_size;
101
102 unsigned int buf_read_pos;
103 unsigned int buf_write_pos;
104 } ao_macosx_t; 99 } ao_macosx_t;
105 100
106 static ao_macosx_t *ao = NULL; 101 static ao_macosx_t *ao = NULL;
107
108 /**
109 * \brief return number of free bytes in the buffer
110 * may only be called by mplayer's thread
111 * \return minimum number of free bytes in buffer, value may change between
112 * two immediately following calls, and the real number of free bytes
113 * might actually be larger!
114 */
115 static int buf_free(void) {
116 int free = ao->buf_read_pos - ao->buf_write_pos - ao->chunk_size;
117 if (free < 0) free += ao->buffer_len;
118 return free;
119 }
120
121 /**
122 * \brief return number of buffered bytes
123 * may only be called by playback thread
124 * \return minimum number of buffered bytes, value may change between
125 * two immediately following calls, and the real number of buffered bytes
126 * might actually be larger!
127 */
128 static int buf_used(void) {
129 int used = ao->buf_write_pos - ao->buf_read_pos;
130 if (used < 0) used += ao->buffer_len;
131 return used;
132 }
133 102
134 /** 103 /**
135 * \brief add data to ringbuffer 104 * \brief add data to ringbuffer
136 */ 105 */
137 static int write_buffer(unsigned char* data, int len){ 106 static int write_buffer(unsigned char* data, int len){
138 int first_len = ao->buffer_len - ao->buf_write_pos; 107 int free = ao->buffer_len - av_fifo_size(ao->buffer);
139 int free = buf_free();
140 if (len > free) len = free; 108 if (len > free) len = free;
141 if (first_len > len) first_len = len; 109 return av_fifo_generic_write(ao->buffer, data, len, NULL);
142 // till end of buffer
143 memcpy (&ao->buffer[ao->buf_write_pos], data, first_len);
144 if (len > first_len) { // we have to wrap around
145 // remaining part from beginning of buffer
146 memcpy (ao->buffer, &data[first_len], len - first_len);
147 }
148 ao->buf_write_pos = (ao->buf_write_pos + len) % ao->buffer_len;
149 return len;
150 } 110 }
151 111
152 /** 112 /**
153 * \brief remove data from ringbuffer 113 * \brief remove data from ringbuffer
154 */ 114 */
155 static int read_buffer(unsigned char* data,int len){ 115 static int read_buffer(unsigned char* data,int len){
156 int first_len = ao->buffer_len - ao->buf_read_pos; 116 int buffered = av_fifo_size(ao->buffer);
157 int buffered = buf_used();
158 if (len > buffered) len = buffered; 117 if (len > buffered) len = buffered;
159 if (first_len > len) first_len = len; 118 return av_fifo_generic_read(ao->buffer, data, len, NULL);
160 // till end of buffer
161 if (data) {
162 memcpy (data, &ao->buffer[ao->buf_read_pos], first_len);
163 if (len > first_len) { // we have to wrap around
164 // remaining part from beginning of buffer
165 memcpy (&data[first_len], ao->buffer, len - first_len);
166 }
167 }
168 ao->buf_read_pos = (ao->buf_read_pos + len) % ao->buffer_len;
169 return len;
170 } 119 }
171 120
172 OSStatus theRenderProc(void *inRefCon, AudioUnitRenderActionFlags *inActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumFrames, AudioBufferList *ioData) 121 OSStatus theRenderProc(void *inRefCon, AudioUnitRenderActionFlags *inActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumFrames, AudioBufferList *ioData)
173 { 122 {
174 int amt=buf_used(); 123 int amt=av_fifo_size(ao->buffer);
175 int req=(inNumFrames)*ao->packetSize; 124 int req=(inNumFrames)*ao->packetSize;
176 125
177 if(amt>req) 126 if(amt>req)
178 amt=req; 127 amt=req;
179 128
491 ao_data.bps = ao_data.samplerate * inDesc.mBytesPerFrame; 440 ao_data.bps = ao_data.samplerate * inDesc.mBytesPerFrame;
492 ao_data.outburst = ao->chunk_size; 441 ao_data.outburst = ao->chunk_size;
493 ao_data.buffersize = ao_data.bps; 442 ao_data.buffersize = ao_data.bps;
494 443
495 ao->num_chunks = (ao_data.bps+ao->chunk_size-1)/ao->chunk_size; 444 ao->num_chunks = (ao_data.bps+ao->chunk_size-1)/ao->chunk_size;
496 ao->buffer_len = (ao->num_chunks + 1) * ao->chunk_size; 445 ao->buffer_len = ao->num_chunks * ao->chunk_size;
497 ao->buffer = calloc(ao->num_chunks + 1, ao->chunk_size); 446 ao->buffer = av_fifo_alloc(ao->buffer_len);
498 447
499 ao_msg(MSGT_AO,MSGL_V, "using %5d chunks of %d bytes (buffer len %d bytes)\n", (int)ao->num_chunks, (int)ao->chunk_size, (int)ao->buffer_len); 448 ao_msg(MSGT_AO,MSGL_V, "using %5d chunks of %d bytes (buffer len %d bytes)\n", (int)ao->num_chunks, (int)ao->chunk_size, (int)ao->buffer_len);
500 449
501 renderCallback.inputProc = theRenderProc; 450 renderCallback.inputProc = theRenderProc;
502 renderCallback.inputProcRefCon = 0; 451 renderCallback.inputProcRefCon = 0;
513 err_out2: 462 err_out2:
514 AudioUnitUninitialize(ao->theOutputUnit); 463 AudioUnitUninitialize(ao->theOutputUnit);
515 err_out1: 464 err_out1:
516 CloseComponent(ao->theOutputUnit); 465 CloseComponent(ao->theOutputUnit);
517 err_out: 466 err_out:
518 free(ao->buffer); 467 av_fifo_free(ao->buffer);
519 free(ao); 468 free(ao);
520 ao = NULL; 469 ao = NULL;
521 return CONTROL_FALSE; 470 return CONTROL_FALSE;
522 } 471 }
523 472
735 ao_data.bps = ao_data.samplerate * (ao->stream_format.mBytesPerPacket/ao->stream_format.mFramesPerPacket); 684 ao_data.bps = ao_data.samplerate * (ao->stream_format.mBytesPerPacket/ao->stream_format.mFramesPerPacket);
736 ao_data.outburst = ao->chunk_size; 685 ao_data.outburst = ao->chunk_size;
737 ao_data.buffersize = ao_data.bps; 686 ao_data.buffersize = ao_data.bps;
738 687
739 ao->num_chunks = (ao_data.bps+ao->chunk_size-1)/ao->chunk_size; 688 ao->num_chunks = (ao_data.bps+ao->chunk_size-1)/ao->chunk_size;
740 ao->buffer_len = (ao->num_chunks + 1) * ao->chunk_size; 689 ao->buffer_len = ao->num_chunks * ao->chunk_size;
741 ao->buffer = calloc(ao->num_chunks + 1, ao->chunk_size); 690 ao->buffer = av_fifo_alloc(ao->buffer_len);
742 691
743 ao_msg(MSGT_AO,MSGL_V, "using %5d chunks of %d bytes (buffer len %d bytes)\n", (int)ao->num_chunks, (int)ao->chunk_size, (int)ao->buffer_len); 692 ao_msg(MSGT_AO,MSGL_V, "using %5d chunks of %d bytes (buffer len %d bytes)\n", (int)ao->num_chunks, (int)ao->chunk_size, (int)ao->buffer_len);
744 693
745 694
746 /* Add IOProc callback. */ 695 /* Add IOProc callback. */
780 i_param_size, &ao->i_hog_pid); 729 i_param_size, &ao->i_hog_pid);
781 if (err != noErr) 730 if (err != noErr)
782 ao_msg(MSGT_AO, MSGL_WARN, "Could not release hogmode: [%4.4s]\n", 731 ao_msg(MSGT_AO, MSGL_WARN, "Could not release hogmode: [%4.4s]\n",
783 (char *)&err); 732 (char *)&err);
784 } 733 }
785 free(ao->buffer); 734 av_fifo_free(ao->buffer);
786 free(ao); 735 free(ao);
787 ao = NULL; 736 ao = NULL;
788 return CONTROL_FALSE; 737 return CONTROL_FALSE;
789 } 738 }
790 739
979 const AudioTimeStamp * inInputTime, 928 const AudioTimeStamp * inInputTime,
980 AudioBufferList * outOutputData, 929 AudioBufferList * outOutputData,
981 const AudioTimeStamp * inOutputTime, 930 const AudioTimeStamp * inOutputTime,
982 void * threadGlobals ) 931 void * threadGlobals )
983 { 932 {
984 int amt = buf_used(); 933 int amt = av_fifo_size(ao->buffer);
985 int req = outOutputData->mBuffers[ao->i_stream_index].mDataByteSize; 934 int req = outOutputData->mBuffers[ao->i_stream_index].mDataByteSize;
986 935
987 if (amt > req) 936 if (amt > req)
988 amt = req; 937 amt = req;
989 if (amt) 938 if (amt)
1028 977
1029 /* set variables and buffer to initial state */ 978 /* set variables and buffer to initial state */
1030 static void reset(void) 979 static void reset(void)
1031 { 980 {
1032 audio_pause(); 981 audio_pause();
1033 /* reset ring-buffer state */ 982 av_fifo_reset(ao->buffer);
1034 ao->buf_read_pos=0;
1035 ao->buf_write_pos=0;
1036
1037 return;
1038 } 983 }
1039 984
1040 985
1041 /* return available space */ 986 /* return available space */
1042 static int get_space(void) 987 static int get_space(void)
1043 { 988 {
1044 return buf_free(); 989 return ao->buffer_len - av_fifo_size(ao->buffer);
1045 } 990 }
1046 991
1047 992
1048 /* return delay until audio is played */ 993 /* return delay until audio is played */
1049 static float get_delay(void) 994 static float get_delay(void)
1050 { 995 {
1051 int buffered = ao->buffer_len - ao->chunk_size - buf_free(); // could be less
1052 // inaccurate, should also contain the data buffered e.g. by the OS 996 // inaccurate, should also contain the data buffered e.g. by the OS
1053 return (float)(buffered)/(float)ao_data.bps; 997 return (float)av_fifo_size(ao->buffer)/(float)ao_data.bps;
1054 } 998 }
1055 999
1056 1000
1057 /* unload plugin and deregister from coreaudio */ 1001 /* unload plugin and deregister from coreaudio */
1058 static void uninit(int immed) 1002 static void uninit(int immed)
1059 { 1003 {
1060 OSStatus err = noErr; 1004 OSStatus err = noErr;
1061 UInt32 i_param_size = 0; 1005 UInt32 i_param_size = 0;
1062 1006
1063 if (!immed) { 1007 if (!immed) {
1064 long long timeleft=(1000000LL*buf_used())/ao_data.bps; 1008 long long timeleft=(1000000LL*av_fifo_size(ao->buffer))/ao_data.bps;
1065 ao_msg(MSGT_AO,MSGL_DBG2, "%d bytes left @%d bps (%d usec)\n", buf_used(), ao_data.bps, (int)timeleft); 1009 ao_msg(MSGT_AO,MSGL_DBG2, "%d bytes left @%d bps (%d usec)\n", av_fifo_size(ao->buffer), ao_data.bps, (int)timeleft);
1066 usec_sleep((int)timeleft); 1010 usec_sleep((int)timeleft);
1067 } 1011 }
1068 1012
1069 if (!ao->b_digital) { 1013 if (!ao->b_digital) {
1070 AudioOutputUnitStop(ao->theOutputUnit); 1014 AudioOutputUnitStop(ao->theOutputUnit);
1113 kAudioDevicePropertyHogMode, i_param_size, &ao->i_hog_pid); 1057 kAudioDevicePropertyHogMode, i_param_size, &ao->i_hog_pid);
1114 if (err != noErr) ao_msg(MSGT_AO, MSGL_WARN, "Could not release hogmode: [%4.4s]\n", (char *)&err); 1058 if (err != noErr) ao_msg(MSGT_AO, MSGL_WARN, "Could not release hogmode: [%4.4s]\n", (char *)&err);
1115 } 1059 }
1116 } 1060 }
1117 1061
1118 free(ao->buffer); 1062 av_fifo_free(ao->buffer);
1119 free(ao); 1063 free(ao);
1120 ao = NULL; 1064 ao = NULL;
1121 } 1065 }
1122 1066
1123 1067