
Author: ods15 Date: Sat Nov 18 12:57:30 2006 New Revision: 233 Modified: trunk/libnut/demuxer.c Log: fix up get_headers() to be more robust and correct by making it more like the first loop described in the nut spec Modified: trunk/libnut/demuxer.c ============================================================================== --- trunk/libnut/demuxer.c (original) +++ trunk/libnut/demuxer.c Sat Nov 18 12:57:30 2006 @@ -302,15 +302,17 @@ return err; } -static int get_stream_header(nut_context_t * nut, int id) { +static int get_stream_header(nut_context_t * nut) { input_buffer_t itmp, * tmp = new_mem_buffer(&itmp); - stream_context_t * sc = &nut->sc[id]; + stream_context_t * sc; int i, err = 0; CHECK(get_header(nut->i, tmp)); GET_V(tmp, i); - ERROR(i != id, NUT_ERR_BAD_STREAM_ORDER); + ERROR(i > nut->stream_count, NUT_ERR_BAD_STREAM_ORDER); + sc = &nut->sc[i]; + if (sc->sh.type != -1) return 0; // we've already taken care of this stream GET_V(tmp, sc->sh.type); CHECK(get_vb(nut->alloc, tmp, &sc->sh.fourcc_len, &sc->sh.fourcc)); @@ -337,6 +339,9 @@ GET_V(tmp, sc->sh.channel_count); // ### is channel count staying in spec break; } + + SAFE_CALLOC(nut->alloc, sc->pts_cache, sizeof(int64_t), sc->sh.decode_delay); + for (i = 0; i < sc->sh.decode_delay; i++) sc->pts_cache[i] = -1; err_out: return err; } @@ -403,59 +408,6 @@ return err; } -static int skip_reserved_headers(nut_context_t * nut, uint64_t stop_startcode) { - int err; - uint64_t tmp; - CHECK(get_bytes(nut->i, 8, &tmp)); - while (tmp != SYNCPOINT_STARTCODE && tmp != stop_startcode) { - ERROR(tmp >> 56 != 'N', NUT_ERR_NOT_FRAME_NOT_N); - CHECK(get_header(nut->i, NULL)); - CHECK(get_bytes(nut->i, 8, &tmp)); - } - nut->i->buf_ptr -= 8; -err_out: - return err; -} - -static int get_headers(nut_context_t * nut, int read_info) { - int i, err; - uint64_t tmp; - - CHECK(get_bytes(nut->i, 8, &tmp)); - assert(tmp == MAIN_STARTCODE); // sanity, get_headers should only be called in this situation - CHECK(get_main_header(nut)); - - SAFE_CALLOC(nut->alloc, nut->sc, sizeof(stream_context_t), nut->stream_count); - - for (i = 0; i < nut->stream_count; i++) { - int j; - CHECK(skip_reserved_headers(nut, STREAM_STARTCODE)); - CHECK(get_bytes(nut->i, 8, &tmp)); - ERROR(tmp != STREAM_STARTCODE, NUT_ERR_NOSTREAM_STARTCODE); - CHECK(get_stream_header(nut, i)); - SAFE_CALLOC(nut->alloc, nut->sc[i].pts_cache, sizeof(int64_t), nut->sc[i].sh.decode_delay); - for (j = 0; j < nut->sc[i].sh.decode_delay; j++) nut->sc[i].pts_cache[j] = -1; - } - if (read_info) { - // FIXME this skip_reserved_headers() will skip INDEX_STARTCODE - CHECK(skip_reserved_headers(nut, INFO_STARTCODE)); - CHECK(get_bytes(nut->i, 8, &tmp)); - while (tmp == INFO_STARTCODE) { - nut->info_count++; - SAFE_REALLOC(nut->alloc, nut->info, sizeof(nut_info_packet_t), nut->info_count + 1); - memset(&nut->info[nut->info_count - 1], 0, sizeof(nut_info_packet_t)); - CHECK(get_info_header(nut, &nut->info[nut->info_count - 1])); - CHECK(skip_reserved_headers(nut, INFO_STARTCODE)); - CHECK(get_bytes(nut->i, 8, &tmp)); - } - nut->info[nut->info_count].count = -1; - nut->i->buf_ptr -= 8; - } -err_out: - assert(err != NUT_ERR_EAGAIN); // EAGAIN is illegal here!! - return err; -} - static int add_syncpoint(nut_context_t * nut, syncpoint_t sp, uint64_t * pts, uint64_t * eor, int * out) { syncpoint_list_t * sl = &nut->syncpoints; int i, j, err = 0; @@ -566,24 +518,20 @@ static int get_index(nut_context_t * nut) { input_buffer_t itmp, * tmp = new_mem_buffer(&itmp); - int err = 0; + int i, err = 0; + uint64_t max_pts; syncpoint_list_t * sl = &nut->syncpoints; - uint64_t x; - int i; - - CHECK(get_bytes(nut->i, 8, &x)); - ERROR(x != INDEX_STARTCODE, NUT_ERR_GENERAL_ERROR); CHECK(get_header(nut->i, tmp)); - GET_V(tmp, x); + GET_V(tmp, max_pts); for (i = 0; i < nut->stream_count; i++) { - TO_PTS(max, x) + TO_PTS(max, max_pts) nut->sc[i].sh.max_pts = convert_ts(max_p, nut->tb[max_t], TO_TB(i)); } - GET_V(tmp, x); - sl->alloc_len = sl->len = x; + GET_V(tmp, sl->len); + sl->alloc_len = sl->len; SAFE_REALLOC(nut->alloc, sl->s, sizeof(syncpoint_t), sl->alloc_len); SAFE_REALLOC(nut->alloc, sl->pts, nut->stream_count * sizeof(uint64_t), sl->alloc_len); SAFE_REALLOC(nut->alloc, sl->eor, nut->stream_count * sizeof(uint64_t), sl->alloc_len); @@ -602,6 +550,7 @@ uint64_t last_pts = 0; // all of pts[] array is off by one. using 0 for last pts is equivalent to -1 in spec. for (j = 0; j < sl->len; ) { int type, n, flag; + uint64_t x; GET_V(tmp, x); type = x & 1; x >>= 1; @@ -665,8 +614,12 @@ CHECK(get_bytes(nut->i, 1, &tmp)); break; case MAIN_STARTCODE: + while (tmp != SYNCPOINT_STARTCODE) { + ERROR(tmp >> 56 != 'N', NUT_ERR_NOT_FRAME_NOT_N); + CHECK(get_header(nut->i, NULL)); + CHECK(get_bytes(nut->i, 8, &tmp)); + } nut->i->buf_ptr -= 8; - CHECK(skip_reserved_headers(nut, SYNCPOINT_STARTCODE)); return -1; case INFO_STARTCODE: if (nut->dopts.new_info && !nut->seek_status) { CHECK(get_info_header(nut, &info)); @@ -784,10 +737,9 @@ if ((err = get_header(nut->i, NULL)) == NUT_ERR_EAGAIN) goto err_out; if (err) { tmp = err = 0; break; } // bad - if ((err = get_bytes(nut->i, 8, &tmp)) == NUT_ERR_EAGAIN) goto err_out; - assert(!err || err == NUT_ERR_EOF); // the only possibilities // EOF is a legal error here - when reading the last headers in file - if (err == NUT_ERR_EOF) { err = 0; tmp = SYNCPOINT_STARTCODE; } + if ((err = get_bytes(nut->i, 8, &tmp)) == NUT_ERR_EOF) { err = 0; tmp = SYNCPOINT_STARTCODE; } + ERROR(err, err); // if get_bytes returns EAGAIN or a memory error, check for that } while (tmp != SYNCPOINT_STARTCODE); if (tmp == SYNCPOINT_STARTCODE) { // success! nut->last_headers = pos; @@ -901,25 +853,58 @@ return err; } -int nut_read_headers(nut_context_t * nut, nut_stream_header_t * s [], nut_info_packet_t * info []) { +static int get_headers(nut_context_t * nut, int read_info) { int i, err = 0; uint64_t tmp; - syncpoint_t sp; - if (!nut->sc) { // we already have headers, we were called just for index - if (!nut->last_headers) CHECK(find_main_headers(nut)); - CHECK(get_headers(nut, !!info)); + CHECK(get_bytes(nut->i, 8, &tmp)); + assert(tmp == MAIN_STARTCODE); // sanity, get_headers should only be called in this situation + CHECK(get_main_header(nut)); - if (nut->dopts.read_index) { // check for index right after main headers - CHECK(skip_reserved_headers(nut, INDEX_STARTCODE)); - CHECK(get_bytes(nut->i, 8, &tmp)); - nut->i->buf_ptr -= 8; - if (tmp == INDEX_STARTCODE) nut->seek_status = 2; // signals to not seek to find index - flush_buf(nut->i); + SAFE_CALLOC(nut->alloc, nut->sc, sizeof(stream_context_t), nut->stream_count); + for (i = 0; i < nut->stream_count; i++) nut->sc[i].sh.type = -1; + + CHECK(get_bytes(nut->i, 8, &tmp)); + + while (tmp != SYNCPOINT_STARTCODE) { + ERROR(tmp >> 56 != 'N', NUT_ERR_NOT_FRAME_NOT_N); + if (tmp == STREAM_STARTCODE) { + CHECK(get_stream_header(nut)); + } else if (tmp == INFO_STARTCODE && read_info) { + SAFE_REALLOC(nut->alloc, nut->info, sizeof(nut_info_packet_t), ++nut->info_count + 1); + memset(&nut->info[nut->info_count - 1], 0, sizeof(nut_info_packet_t)); + CHECK(get_info_header(nut, &nut->info[nut->info_count - 1])); + nut->info[nut->info_count].count = -1; + } else if (tmp == INDEX_STARTCODE && nut->dopts.read_index) { + CHECK(get_index(nut)); // usually you don't care about get_index() errors, but nothing except a memory error can happen here + } else { + CHECK(get_header(nut->i, NULL)); } + // EOF is a legal error here - when reading the last headers in file + if ((err = get_bytes(nut->i, 8, &tmp)) == NUT_ERR_EOF) { tmp = err = 0; break; } + ERROR(err, err); // it's just barely possible for get_bytes to return a memory error, check for that } + if (tmp == SYNCPOINT_STARTCODE) nut->i->buf_ptr -= 8; + + for (i = 0; i < nut->stream_count; i++) ERROR(nut->sc[i].sh.type == -1, NUT_ERR_NOSTREAM_STARTCODE); + +err_out: + assert(err != NUT_ERR_EAGAIN); // EAGAIN is illegal here!! + return err; +} + +int nut_read_headers(nut_context_t * nut, nut_stream_header_t * s [], nut_info_packet_t * info []) { + int i, err = 0; + syncpoint_t sp; + + // step 1 - find headers and load to memory + if (!nut->last_headers) CHECK(find_main_headers(nut)); - if (nut->dopts.read_index & 1) { // we already have index, we were called just for the final syncpoint search + // step 2 - parse headers + if (!nut->sc) CHECK(get_headers(nut, !!info)); + + // step 3 - search for index if necessary + if (nut->dopts.read_index & 1) { uint64_t idx_ptr; if (nut->seek_status <= 1) { if (nut->seek_status == 0) { @@ -934,17 +919,22 @@ if (nut->dopts.read_index) { if (nut->seek_status == 1) seek_buf(nut->i, idx_ptr, SEEK_SET); nut->seek_status = 2; - // only EAGAIN from get_index is interesting - if ((err = get_index(nut)) == NUT_ERR_EAGAIN) goto err_out; + CHECK(get_bytes(nut->i, 8, &idx_ptr)); + if (idx_ptr != INDEX_STARTCODE) err = 1; + else { + // only EAGAIN from get_index is interesting + if ((err = get_index(nut)) == NUT_ERR_EAGAIN) goto err_out; + } if (err) nut->dopts.read_index = 0; else nut->dopts.read_index = 2; err = 0; } - if (nut->before_seek) seek_buf(nut->i, nut->before_seek, SEEK_SET); + if (nut->before_seek && nut->last_headers <= 1024) seek_buf(nut->i, nut->before_seek, SEEK_SET); nut->before_seek = 0; + nut->seek_status = 0; } - // last step - find the first syncpoint in file + // step 4 - find the first syncpoint in file if (nut->last_headers > 1024 && !nut->seek_status) { // the headers weren't found in begginning of file assert(nut->i->isc.seek);
participants (1)
-
ods15