From 008c368c87873615ccbe8bc0b3482d93ae15779d Mon Sep 17 00:00:00 2001 From: Michael Giacomelli Date: Sat, 2 Jan 2010 20:54:55 +0000 Subject: Commit first part of FS#10832 by Juliusz Chroboczek. Allows playback of unstreamable AAC/ALAC files by stepping through the file to find the index, potientially rebuffering. This is likely to impose a battery life hit on files which are unstreamable and not much smaller then the buffer, but should not impact streamable files at all. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@24147 a1c6a512-1295-4272-9138-f99709370657 --- apps/codecs/libm4a/demux.c | 20 +++++++++++--------- apps/codecs/libm4a/m4a.c | 7 ++++++- apps/codecs/libm4a/m4a.h | 1 + apps/metadata/mp4.c | 13 +++++++------ 4 files changed, 25 insertions(+), 16 deletions(-) diff --git a/apps/codecs/libm4a/demux.c b/apps/codecs/libm4a/demux.c index 00fd3132aa..9f887b6b83 100644 --- a/apps/codecs/libm4a/demux.c +++ b/apps/codecs/libm4a/demux.c @@ -746,7 +746,10 @@ int qtmovie_read(stream_t *file, demux_res_t *demux_res) chunk_len = stream_read_uint32(qtmovie.stream); if (stream_eof(qtmovie.stream)) { - return 0; + if(qtmovie.res->mdat_offset == 0 || qtmovie.res->format == 0) + return 0; + stream_seek(qtmovie.stream, qtmovie.res->mdat_offset); + return 1; } if (chunk_len == 1) @@ -767,20 +770,19 @@ int qtmovie_read(stream_t *file, demux_res_t *demux_res) return 0; } break; - /* once we hit mdat we stop reading and return. - * this is on the assumption that there is no furhter interesting - * stuff in the stream. if there is stuff will fail (:()). - * But we need the read pointer to be at the mdat stuff - * for the decoder. And we don't want to rely on fseek/ftell, - * as they may not always be avilable */ case MAKEFOURCC('m','d','a','t'): read_chunk_mdat(&qtmovie, chunk_len); /* Keep track of start of stream in file - used for seeking */ qtmovie.res->mdat_offset=stream_tell(qtmovie.stream); /* There can be empty mdats before the real one. If so, skip them */ - if (qtmovie.res->mdat_len > 0) { + if (qtmovie.res->mdat_len == 0) + break; + /* If we've already seen the format, assume there's nothing + interesting after the mdat chunk (the file is "streamable"). + This avoids having to seek, which might cause rebuffering. */ + if(qtmovie.res->format > 0) return 1; - } + stream_skip(qtmovie.stream, chunk_len - 8); break; /* these following atoms can be skipped !!!! */ diff --git a/apps/codecs/libm4a/m4a.c b/apps/codecs/libm4a/m4a.c index 92e619db35..42295e76ee 100644 --- a/apps/codecs/libm4a/m4a.c +++ b/apps/codecs/libm4a/m4a.c @@ -103,7 +103,12 @@ uint8_t stream_read_uint8(stream_t *stream) void stream_skip(stream_t *stream, size_t skip) { - stream->ci->advance_buffer(skip); + stream->ci->advance_buffer(skip); +} + +void stream_seek(stream_t *stream, size_t offset) +{ + stream->ci->seek_buffer(offset); } int stream_eof(stream_t *stream) diff --git a/apps/codecs/libm4a/m4a.h b/apps/codecs/libm4a/m4a.h index e2d4376d12..066f54b722 100644 --- a/apps/codecs/libm4a/m4a.h +++ b/apps/codecs/libm4a/m4a.h @@ -113,6 +113,7 @@ int8_t stream_read_int8(stream_t *stream); uint8_t stream_read_uint8(stream_t *stream); void stream_skip(stream_t *stream, size_t skip); +void stream_seek(stream_t *stream, size_t offset); int stream_eof(stream_t *stream); diff --git a/apps/metadata/mp4.c b/apps/metadata/mp4.c index 44bc68eb5c..c5a525d9c5 100644 --- a/apps/metadata/mp4.c +++ b/apps/metadata/mp4.c @@ -548,6 +548,7 @@ static bool read_mp4_container(int fd, struct mp3entry* id3, uint32_t type; uint32_t handler = 0; bool rc = true; + bool done = false; do { @@ -681,6 +682,10 @@ static bool read_mp4_container(int fd, struct mp3entry* id3, case MP4_mdat: id3->filesize = size; + if(id3->samples > 0) { + /* We've already seen the moov chunk. */ + done = true; + } break; case MP4_chpl: @@ -708,15 +713,11 @@ static bool read_mp4_container(int fd, struct mp3entry* id3, } /* Skip final seek. */ - if (id3->filesize == 0) + if (!done) { lseek(fd, size, SEEK_CUR); } - } - while (rc && (size_left > 0) && (errno == 0) && (id3->filesize == 0)); - /* Break on non-zero filesize, since Rockbox currently doesn't support - * metadata after the mdat atom (which sets the filesize field). - */ + } while (rc && (size_left > 0) && (errno == 0) && !done); return rc; } -- cgit v1.2.3