diff options
| author | Thomas Martitz <kugel@rockbox.org> | 2011-08-14 15:13:00 +0000 |
|---|---|---|
| committer | Thomas Martitz <kugel@rockbox.org> | 2011-08-14 15:13:00 +0000 |
| commit | d1322b71595336740eb5e18e5deed056ddb71c7a (patch) | |
| tree | 812db6a9c2e9d78405ec0ed38465fd88dc5be748 /apps/mpeg.c | |
| parent | 9b9bd73dfb212d4192fccc5fc5e269fc6499139c (diff) | |
| download | rockbox-d1322b71595336740eb5e18e5deed056ddb71c7a.zip rockbox-d1322b71595336740eb5e18e5deed056ddb71c7a.tar.gz rockbox-d1322b71595336740eb5e18e5deed056ddb71c7a.tar.bz2 rockbox-d1322b71595336740eb5e18e5deed056ddb71c7a.tar.xz | |
GSoC/Buflib: Replace all direct accesses to audiobuf with buffer API functions.
Namely, introduce buffer_get_buffer() and buffer_release_buffer().
buffer_get_buffer() aquires all available and grabs a lock, attempting to
call buffer_alloc() or buffer_get_buffer() while this lock is locked will cause
a panicf() (doesn't actually happen, but is for debugging purpose).
buffer_release_buffer() unlocks that lock and can additionally increment the
audiobuf buffer to make an allocation. Pass 0 to only unlock if buffer was
used temporarily only.
buffer_available() is a replacement function to query audiobuflen, i.e. what's
left in the buffer.
Buffer init is moved up in the init chain and handles ipodvideo64mb internally.
Further changes happened to mp3data.c and talk.c as to not call the above API
functions, but get the buffer from callers. The caller is the audio system
which has the buffer lock while mp3data.c and talk mess with the buffer.
mpeg.c now implements some buffer related functions of playback.h, especially
audio_get_buffer(), allowing to reduce #ifdef hell a tiny bit.
audiobuf and audiobufend are local to buffer.c now.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@30308 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/mpeg.c')
| -rw-r--r-- | apps/mpeg.c | 89 |
1 files changed, 66 insertions, 23 deletions
diff --git a/apps/mpeg.c b/apps/mpeg.c index b11445f..a0182ad 100644 --- a/apps/mpeg.c +++ b/apps/mpeg.c @@ -37,6 +37,7 @@ #include "mp3data.h" #include "buffer.h" #include "mp3_playback.h" +#include "talk.h" #include "sound.h" #include "bitswap.h" #include "appevents.h" @@ -144,19 +145,19 @@ static unsigned int mpeg_errno; static bool playing = false; /* We are playing an MP3 stream */ static bool is_playing = false; /* We are (attempting to) playing MP3 files */ static bool paused; /* playback is paused */ +static char* mpeg_audiobuf; /* the audio buffer */ +static long audiobuflen; /* length of the audio buffer */ #ifdef SIMULATOR static char mpeg_stack[DEFAULT_STACK_SIZE]; static struct mp3entry taginfo; - #else /* !SIMULATOR */ static struct event_queue mpeg_queue SHAREDBSS_ATTR; static long mpeg_stack[(DEFAULT_STACK_SIZE + 0x1000)/sizeof(long)]; -static int audiobuflen; static int audiobuf_write; static int audiobuf_swapwrite; -static int audiobuf_read; +static long audiobuf_read; static int mpeg_file; @@ -490,6 +491,18 @@ unsigned long mpeg_get_last_header(void) #endif /* !SIMULATOR */ } + +unsigned char * audio_get_buffer(bool talk_buf, size_t *buffer_size) +{ + (void)talk_buf; /* always grab the voice buffer for now */ + + audio_hard_stop(); + if (buffer_size) /* special case for talk_init() */ + return buffer_get_buffer(buffer_size); + return NULL; +} + + #ifndef SIMULATOR /* Send callback events to notify about removing old tracks. */ static void generate_unbuffer_events(void) @@ -708,7 +721,7 @@ void rec_tick(void) xor_b(0x08, &PADRH); /* Set PR inactive */ - audiobuf[audiobuf_write++] = data; + mpeg_audiobuf[audiobuf_write++] = data; if (audiobuf_write >= audiobuflen) audiobuf_write = 0; @@ -825,7 +838,7 @@ static void transfer_end(unsigned char** ppbuf, size_t* psize) } *psize = last_dma_chunk_size & 0xffff; - *ppbuf = audiobuf + audiobuf_read; + *ppbuf = mpeg_audiobuf + audiobuf_read; track = get_trackdata(0); if(track) track->id3.offset += last_dma_chunk_size; @@ -1128,7 +1141,7 @@ static void start_playback_if_ready(void) playing = true; last_dma_chunk_size = MIN(0x2000, get_unplayed_space_current_song()); - mp3_play_data(audiobuf + audiobuf_read, last_dma_chunk_size, transfer_end); + mp3_play_data(mpeg_audiobuf + audiobuf_read, last_dma_chunk_size, transfer_end); dma_underrun = false; if (!paused) @@ -1173,7 +1186,7 @@ static bool swap_one_chunk(void) amount_to_swap = MIN(audiobuf_write - audiobuf_swapwrite, amount_to_swap); - bitswap(audiobuf + audiobuf_swapwrite, amount_to_swap); + bitswap(mpeg_audiobuf + audiobuf_swapwrite, amount_to_swap); audiobuf_swapwrite += amount_to_swap; if(audiobuf_swapwrite >= audiobuflen) @@ -1341,7 +1354,7 @@ static void mpeg_thread(void) track_change(); audiobuf_read = get_trackdata(0)->mempos; last_dma_chunk_size = MIN(0x2000, get_unplayed_space_current_song()); - mp3_play_data(audiobuf + audiobuf_read, last_dma_chunk_size, transfer_end); + mp3_play_data(mpeg_audiobuf + audiobuf_read, last_dma_chunk_size, transfer_end); dma_underrun = false; last_dma_tick = current_tick; @@ -1501,7 +1514,7 @@ static void mpeg_thread(void) /* resume will start at new position */ last_dma_chunk_size = MIN(0x2000, get_unplayed_space_current_song()); - mp3_play_data(audiobuf + audiobuf_read, + mp3_play_data(mpeg_audiobuf + audiobuf_read, last_dma_chunk_size, transfer_end); dma_underrun = false; } @@ -1632,7 +1645,7 @@ static void mpeg_thread(void) { DEBUGF("R\n"); t1 = current_tick; - len = read(mpeg_file, audiobuf + audiobuf_write, + len = read(mpeg_file, mpeg_audiobuf + audiobuf_write, amount_to_read); if(len > 0) { @@ -1659,7 +1672,7 @@ static void mpeg_thread(void) if(tagptr >= audiobuflen) tagptr -= audiobuflen; - if(audiobuf[tagptr] != tag[i]) + if(mpeg_audiobuf[tagptr] != tag[i]) { taglen = 0; break; @@ -1773,19 +1786,20 @@ static void mpeg_thread(void) startpos = prerecord_buffer[startpos].mempos; DEBUGF("Start looking at address %x (%x)\n", - audiobuf+startpos, startpos); + mpeg_audiobuf+startpos, startpos); saved_header = mpeg_get_last_header(); mem_find_next_frame(startpos, &offset, 1800, - saved_header); + saved_header, mpeg_audiobuf, + audiobuflen); audiobuf_read = startpos + offset; if(audiobuf_read >= audiobuflen) audiobuf_read -= audiobuflen; DEBUGF("New audiobuf_read address: %x (%x)\n", - audiobuf+audiobuf_read, audiobuf_read); + mpeg_audiobuf+audiobuf_read, audiobuf_read); level = disable_irq_save(); num_rec_bytes = get_unsaved_space(); @@ -1894,7 +1908,8 @@ static void mpeg_thread(void) save_endpos += audiobuflen; rc = mem_find_next_frame(save_endpos, &offset, 1800, - saved_header); + saved_header, mpeg_audiobuf, + audiobuflen); if (!rc) /* No header found, save whole buffer */ offset = 1800; @@ -1936,7 +1951,7 @@ static void mpeg_thread(void) #elif MEMORYSIZE == 8 amount_to_save = MIN(0x100000, amount_to_save); #endif - rc = write(mpeg_file, audiobuf + audiobuf_read, + rc = write(mpeg_file, mpeg_audiobuf + audiobuf_read, amount_to_save); if (rc < 0) { @@ -2256,21 +2271,21 @@ static void prepend_header(void) if(audiobuf_read < 0) { /* Clear the bottom half */ - memset(audiobuf, 0, audiobuf_read + MPEG_RESERVED_HEADER_SPACE); + memset(mpeg_audiobuf, 0, audiobuf_read + MPEG_RESERVED_HEADER_SPACE); /* And the top half */ audiobuf_read += audiobuflen; - memset(audiobuf + audiobuf_read, 0, audiobuflen - audiobuf_read); + memset(mpeg_audiobuf + audiobuf_read, 0, audiobuflen - audiobuf_read); } else { - memset(audiobuf + audiobuf_read, 0, MPEG_RESERVED_HEADER_SPACE); + memset(mpeg_audiobuf + audiobuf_read, 0, MPEG_RESERVED_HEADER_SPACE); } /* Copy the empty ID3 header */ startpos = audiobuf_read; for(i = 0; i < sizeof(empty_id3_header); i++) { - audiobuf[startpos++] = empty_id3_header[i]; + mpeg_audiobuf[startpos++] = empty_id3_header[i]; if(startpos == audiobuflen) startpos = 0; } @@ -2297,7 +2312,8 @@ static void update_header(void) /* saved_header is saved right before stopping the MAS */ framelen = create_xing_header(fd, 0, last_rec_bytes, xing_buffer, frames, last_rec_time * (1000/HZ), - saved_header, NULL, false); + saved_header, NULL, false, + mpeg_audiobuf, audiobuflen); lseek(fd, MPEG_RESERVED_HEADER_SPACE - framelen, SEEK_SET); write(fd, xing_buffer, framelen); @@ -2645,8 +2661,22 @@ void audio_set_recording_options(struct audio_recording_options *options) #endif /* SIMULATOR */ #endif /* CONFIG_CODEC == MAS3587F */ +static void audio_reset_buffer(void) +{ + size_t bufsize; /* dont break strict-aliasing */ + talk_buffer_steal(); /* will use the mp3 buffer */ + + /* release buffer on behalf of any audio_get_buffer() caller, + * non-fatal if there was none */ + buffer_release_buffer(0); + /* re-aquire */ + mpeg_audiobuf = buffer_get_buffer(&bufsize); + audiobuflen = bufsize; +} + void audio_play(long offset) { + audio_reset_buffer(); #ifdef SIMULATOR char name_buf[MAX_PATH+1]; const char* trackname; @@ -2676,7 +2706,6 @@ void audio_play(long offset) } while(1); #else /* !SIMULATOR */ is_playing = true; - queue_post(&mpeg_queue, MPEG_PLAY, offset); #endif /* !SIMULATOR */ @@ -2700,6 +2729,8 @@ void audio_stop(void) is_playing = false; playing = false; #endif /* SIMULATOR */ + /* give voice our entire buffer */ + talkbuf_init(mpeg_audiobuf); } /* dummy */ @@ -2708,6 +2739,14 @@ void audio_stop_recording(void) audio_stop(); } +void audio_hard_stop(void) +{ + audio_stop(); + /* tell voice we obtain the buffer before freeing */ + talk_buffer_steal(); + buffer_release_buffer(0); +} + void audio_pause(void) { #ifndef SIMULATOR @@ -2864,8 +2903,12 @@ void audio_init(void) if (global_settings.cuesheet) curr_cuesheet = (struct cuesheet*)buffer_alloc(sizeof(struct cuesheet)); + size_t bufsize; /* don't break strict-aliasing */ + mpeg_audiobuf = buffer_get_buffer(&bufsize); + audiobuflen = bufsize; + /* give voice buffer until we start to play */ + talkbuf_init(mpeg_audiobuf); #ifndef SIMULATOR - audiobuflen = audiobufend - audiobuf; queue_init(&mpeg_queue, true); #endif /* !SIMULATOR */ create_thread(mpeg_thread, mpeg_stack, |