[NUT-devel] [nut]: r233 - trunk/libnut/demuxer.c
ods15
subversion at mplayerhq.hu
Sat Nov 18 12:57:30 CET 2006
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);
More information about the NUT-devel
mailing list