[NUT-devel] NUT SVN: r63 - in trunk: libnut nututils

ods15 at natsuki.mplayerhq.hu ods15 at natsuki.mplayerhq.hu
Fri Feb 24 08:31:25 CET 2006


Author: ods15
Date: 2006-02-24 08:31:25 +0100 (Fri, 24 Feb 2006)
New Revision: 63

Modified:
   trunk/libnut/demuxer.c
   trunk/libnut/muxer.c
   trunk/libnut/priv.h
   trunk/nututils/demux_avi.c
Log:
EOR for libnut seeking and index


Modified: trunk/libnut/demuxer.c
===================================================================
--- trunk/libnut/demuxer.c	2006-02-12 17:56:55 UTC (rev 62)
+++ trunk/libnut/demuxer.c	2006-02-24 07:31:25 UTC (rev 63)
@@ -301,7 +301,7 @@
 	return err;
 }
 
-static int add_syncpoint(nut_context_t * nut, syncpoint_t sp, uint64_t * pts) {
+static int add_syncpoint(nut_context_t * nut, syncpoint_t sp, uint64_t * pts, uint64_t * eor) {
 	syncpoint_list_t * sl = &nut->syncpoints;
 	int i, j;
 
@@ -309,12 +309,14 @@
 		off_t pos = sl->s[i].pos >> 1;
 		if (pos > sp.pos) continue;
 		if (sp.pos < pos + 8) { // syncpoint already in list
-			sl->s[i].pos = (sp.pos << 1) | (sl->s[i].pos & 1);
+			sl->s[i].pos = (sp.pos << 1) | (sl->s[i].pos & 1); // refine accuracy of syncpoint position
 			if (pts) {
 				sl->s[i].pos |= 1;
 				for (j = 0; j < nut->stream_count; j++) {
 					assert(!sl->pts[i * nut->stream_count + j] || sl->pts[i * nut->stream_count + j] == pts[j]);
 					sl->pts[i * nut->stream_count + j] = pts[j];
+					assert(!sl->eor[i * nut->stream_count + j] || sl->eor[i * nut->stream_count + j] == eor[j]);
+					sl->eor[i * nut->stream_count + j] = eor[j];
 				}
 			}
 			return i;
@@ -326,14 +328,19 @@
 		sl->alloc_len += PREALLOC_SIZE/4;
 		sl->s = realloc(sl->s, sl->alloc_len * sizeof(syncpoint_t));
 		sl->pts = realloc(sl->pts, sl->alloc_len * nut->stream_count * sizeof(uint64_t));
+		sl->eor = realloc(sl->eor, sl->alloc_len * nut->stream_count * sizeof(uint64_t));
 	}
 	memmove(sl->s + i + 1, sl->s + i, (sl->len - i) * sizeof(syncpoint_t));
 	memmove(sl->pts + (i + 1) * nut->stream_count, sl->pts + i * nut->stream_count, (sl->len - i) * nut->stream_count * sizeof(uint64_t));
+	memmove(sl->eor + (i + 1) * nut->stream_count, sl->eor + i * nut->stream_count, (sl->len - i) * nut->stream_count * sizeof(uint64_t));
 
 	sl->s[i] = sp;
 	sl->s[i].pos <<= 1; // flag
 	if (pts) sl->s[i].pos |= 1;
-	for (j = 0; j < nut->stream_count; j++) sl->pts[i * nut->stream_count + j] = pts ? pts[j] : 0;
+	for (j = 0; j < nut->stream_count; j++) {
+		sl->pts[i * nut->stream_count + j] = pts ? pts[j] : 0;
+		sl->eor[i * nut->stream_count + j] = eor ? eor[j] : 0;
+	}
 	sl->len++;
 	return i;
 }
@@ -363,12 +370,18 @@
 	if (/*nut->dopts.cache_syncpoints*/1) {
 		int i;
 		uint64_t pts[nut->stream_count];
+		uint64_t eor[nut->stream_count];
 		for (i = 0; i < nut->stream_count; i++) {
 			pts[i] = nut->sc[i].last_key;
 			nut->sc[i].last_key = 0;
+			eor[i] = nut->sc[i].eor;
+			nut->sc[i].eor = 0;
 		}
-		i = add_syncpoint(nut, s, after_seek ? NULL : pts);
-		if (!after_seek) nut->syncpoints.s[i - 1].back_ptr |= 1;
+		if (after_seek) add_syncpoint(nut, s, NULL, NULL);
+		else {
+			i = add_syncpoint(nut, s, pts, eor);
+			nut->syncpoints.s[i - 1].back_ptr |= 1;
+		}
 	} /*else {
 		if (!nut->syncpoints.len) add_syncpoint(nut, s);
 	}*/
@@ -380,7 +393,6 @@
 	input_buffer_t * tmp = new_mem_buffer();
 	int err = 0;
 	syncpoint_list_t * sl = &nut->syncpoints;
-	uint64_t * p;
 	uint64_t x;
 	int i;
 
@@ -399,7 +411,8 @@
 	GET_V(tmp, x);
 	sl->alloc_len = sl->len = x;
 	sl->s = realloc(sl->s, sl->alloc_len * sizeof(syncpoint_t));
-	p = sl->pts = realloc(sl->pts, sl->alloc_len * sizeof(uint64_t) * nut->stream_count);
+	sl->pts = realloc(sl->pts, sl->alloc_len * sizeof(uint64_t) * nut->stream_count);
+	sl->eor = realloc(sl->eor, sl->alloc_len * sizeof(uint64_t) * nut->stream_count);
 
 	for (i = 0; i < sl->len; i++) {
 		GET_V(tmp, x);
@@ -410,7 +423,7 @@
 	}
 	for (i = 0; i < nut->stream_count; i++) {
 		int j;
-		uint64_t last_pts = 0;
+		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;
 			GET_V(tmp, x);
@@ -420,19 +433,26 @@
 			if (type) {
 				flag = x & 1;
 				x >>= 1;
-				while (x--) p[n++ * nut->stream_count + i] = flag;
-				if (n < sl->len) p[n++ * nut->stream_count + i] = !flag;
+				while (x--) sl->pts[n++ * nut->stream_count + i] = flag;
+				if (n < sl->len) sl->pts[n++ * nut->stream_count + i] = !flag;
 			} else {
 				while (x != 1) {
-					p[n++ * nut->stream_count + i] = x & 1;
+					sl->pts[n++ * nut->stream_count + i] = x & 1;
 					x >>= 1;
+					if (n == sl->len) break;
 				}
 			}
 			for(; j < n; j++) {
-				if (!p[j * nut->stream_count + i]) continue;
-				GET_V(tmp, x);
-				last_pts += x;
-				p[j * nut->stream_count + i] = last_pts + 1;
+				int A, B = 0;
+				if (!sl->pts[j * nut->stream_count + i]) continue;
+				GET_V(tmp, A);
+				if (!A) {
+					GET_V(tmp, A);
+					GET_V(tmp, B);
+					sl->eor[j * nut->stream_count + i] = last_pts + A + B;
+				}
+				sl->pts[j * nut->stream_count + i] = last_pts + A;
+				last_pts += A + B;
 			}
 		}
 	}
@@ -558,6 +578,8 @@
 	sc->last_pts = pd->pts;
 	sc->last_dts = get_dts(sc->decode_delay, sc->pts_cache, pd->pts);
 	if (pd->flags & NUT_KEY_STREAM_FLAG && !sc->last_key) sc->last_key = pd->pts + 1;
+	if (pd->flags & NUT_EOR_STREAM_FLAG) sc->eor = pd->pts + 1;
+	else sc->eor = 0;
 }
 
 static int find_syncpoint(nut_context_t * nut, int backwards, syncpoint_t * res, off_t stop) {
@@ -690,6 +712,7 @@
 				nut->sc[i].last_pts = 0;
 				nut->sc[i].last_dts = 0;
 				nut->sc[i].last_key = 0;
+				nut->sc[i].eor = 0;
 				nut->sc[i].sh.max_pts = 0;
 				nut->sc[i].sh.fourcc = NULL;
 				nut->sc[i].sh.codec_specific = NULL;
@@ -822,7 +845,7 @@
 		if (!nut->seek_status) seek_buf(nut->i, 0, SEEK_SET);
 		nut->seek_status = 1;
 		CHECK(find_syncpoint(nut, 0, &s, 0));
-		add_syncpoint(nut, s, NULL);
+		add_syncpoint(nut, s, NULL, NULL);
 		nut->seek_status = 0;
 	}
 
@@ -832,7 +855,7 @@
 		if (!nut->seek_status) seek_buf(nut->i, 0, SEEK_END);
 		nut->seek_status = 1;
 		CHECK(find_syncpoint(nut, 1, &s, 0));
-		i = add_syncpoint(nut, s, NULL);
+		i = add_syncpoint(nut, s, NULL, NULL);
 		assert(i == sl->len-1);
 		sl->s[i].back_ptr |= 1;
 		nut->seek_status = 0;
@@ -925,7 +948,7 @@
 			lop = s.pts;
 		}
 		if (1/*nut->dopts.cache_syncpoints || sl->len == 2*/) {
-			int tmp = add_syncpoint(nut, s, NULL);
+			int tmp = add_syncpoint(nut, s, NULL, NULL);
 			if (!res) i = tmp;
 		}/* else if (sl->len == 3) {
 			if (s.pts > pts) {
@@ -1021,7 +1044,10 @@
 				if (n) break; // pts for all active streams higher than requested pts
 			}
 			if (pd.flags & NUT_KEY_STREAM_FLAG) {
-				if (pd.pts <= pts[pd.stream]>>1) good_key[pd.stream] = begin<<1;
+				if (pd.pts <= pts[pd.stream]>>1) {
+					good_key[pd.stream] = begin<<1;
+					if (pd.flags & NUT_EOR_STREAM_FLAG) good_key[pd.stream] = 0;
+				}
 				if (!end && pd.pts >= pts[pd.stream]>>1) { // forward seek end
 					if (saw_syncpoint) nut->last_syncpoint = 0;
 					nut->i->buf_ptr = buf_before;
@@ -1157,6 +1183,7 @@
 		int sync[nut->stream_count];
 		int good_sync = -2;
 		int last_sync = 0;
+		int backup = -1;
 		for (i = 0; i < nut->stream_count; i++) sync[i] = -1;
 
 		for (i = 1; i < sl->len; i++) {
@@ -1164,19 +1191,25 @@
 			if (!(sl->s[i].pos & 1)) continue;
 			for (j = 0; j < nut->stream_count; j++) {
 				uint64_t tmp = sl->pts[i * nut->stream_count + j];
+				if (pts[j]&1 && tmp--) { // -- because all pts array os off-by-one. zero indicate no keyframe.
+					if ((pts[j] >> 1) < tmp) { if (!last_sync) last_sync = i; }
+					else sync[j] = (i-1);
+				}
+				tmp = sl->eor[i * nut->stream_count + j];
 				if (pts[j]&1 && tmp--) {
-					if ((pts[j] >> 1) < tmp) {
-						if (!last_sync) last_sync = i;
-					} else sync[j] = (i-1);
+					if ((pts[j] >> 1) < tmp) { if (!last_sync) last_sync = i; }
+					else sync[j] = -(i+1); // flag stream eor
 				}
 			}
 		}
 		for (i = 0; i < nut->stream_count; i++) {
 			if (!(pts[i] & 1)) continue;
+			if (sync[i] < -1) { backup = MAX(backup, -sync[i] - 1); continue; } // eor stream
 			if (good_sync == -2 || good_sync > sync[i]) good_sync = sync[i];
 		}
+		if (good_sync == -2) good_sync = backup; // all active streams are eor, just pick a random point, sort of.
 
-		if ((sl->s[sl->len-1].back_ptr & 1) && last_sync && good_sync != -1) {
+		if ((sl->s[sl->len-1].back_ptr & 1) && last_sync && good_sync >= 0) {
 			for (i = good_sync; i <= last_sync; i++) if (!(sl->s[i].pos & 1)) break;
 			if (i != last_sync+1 && good_sync <= last_sync) good_sync = -1;
 		} else good_sync = -1;
@@ -1215,6 +1248,7 @@
 	nut->syncpoints.alloc_len = 0;
 	nut->syncpoints.s = NULL;
 	nut->syncpoints.pts = NULL;
+	nut->syncpoints.eor = NULL;
 
 	nut->fti = NULL;
 	nut->sc = NULL;
@@ -1239,6 +1273,7 @@
 
 	free(nut->syncpoints.s);
 	free(nut->syncpoints.pts);
+	free(nut->syncpoints.eor);
 	free(nut->sc);
 	free(nut->seek_state);
 	free_buffer(nut->i);

Modified: trunk/libnut/muxer.c
===================================================================
--- trunk/libnut/muxer.c	2006-02-12 17:56:55 UTC (rev 62)
+++ trunk/libnut/muxer.c	2006-02-24 07:31:25 UTC (rev 63)
@@ -154,13 +154,17 @@
 		s->alloc_len += PREALLOC_SIZE;
 		s->s = realloc(s->s, s->alloc_len * sizeof(syncpoint_t));
 		s->pts = realloc(s->pts, s->alloc_len * nut->stream_count * sizeof(uint64_t));
+		s->eor = realloc(s->eor, s->alloc_len * nut->stream_count * sizeof(uint64_t));
 	}
 
-	for (i = 0; i < nut->stream_count; i++) s->pts[s->len * nut->stream_count + i] = nut->sc[i].last_key;
+	for (i = 0; i < nut->stream_count; i++) {
+		s->pts[s->len * nut->stream_count + i] = nut->sc[i].last_key;
+		s->eor[s->len * nut->stream_count + i] = nut->sc[i].eor > 0 ? nut->sc[i].eor : 0;
+	}
 	s->s[s->len].pos = nut->last_syncpoint;
 	s->len++;
 
-	for (i = 0; i < nut->stream_count; i++) keys[i] = !!nut->sc[i].eor; // FIXME for eor in index
+	for (i = 0; i < nut->stream_count; i++) keys[i] = !!nut->sc[i].eor;
 	for (i = s->len; --i; ) {
 		int j;
 		int n = 1;
@@ -177,6 +181,7 @@
 	for (i = 0; i < nut->stream_count; i++) {
 		nut->sc[i].last_pts = convert_ts(nut, pts, stream, i);
 		nut->sc[i].last_key = 0;
+		if (nut->sc[i].eor) nut->sc[i].eor = -1; // so we know to ignore this stream in future syncpoints
 	}
 
 	put_bytes(bc, 8, SYNCPOINT_STARTCODE);
@@ -395,7 +400,7 @@
 	}
 
 	for (i = 0; i < nut->stream_count; i++) {
-		uint64_t a, last = 0;
+		uint64_t a, last = 0; // all of pts[] array is off by one. using 0 for last pts is equivalent to -1 in spec.
 		int j;
 		for (j = 0; j < s->len; ) {
 			int k;
@@ -423,8 +428,15 @@
 			j += k;
 			for (k = j - k; k < j; k++) {
 				if (!s->pts[k * nut->stream_count + i]) continue;
-				put_v(tmp, s->pts[k * nut->stream_count + i] - last - 1);
-				last = s->pts[k * nut->stream_count + i] - 1;
+				if (s->eor[k * nut->stream_count + i]) {
+					put_v(tmp, 0);
+					put_v(tmp, s->pts[k * nut->stream_count + i] - last);
+					put_v(tmp, s->eor[k * nut->stream_count + i] - s->pts[k * nut->stream_count + i]);
+					last = s->eor[k * nut->stream_count + i];
+				} else {
+					put_v(tmp, s->pts[k * nut->stream_count + i] - last);
+					last = s->pts[k * nut->stream_count + i];
+				}
 			}
 		}
 	}
@@ -502,6 +514,7 @@
 	nut->syncpoints.alloc_len = 0;
 	nut->syncpoints.s = NULL;
 	nut->syncpoints.pts = NULL;
+	nut->syncpoints.eor = NULL;
 	nut->last_syncpoint = 0;
 
 	for (nut->stream_count = 0; s[nut->stream_count].type >= 0; nut->stream_count++);
@@ -579,6 +592,7 @@
 
 	free(nut->syncpoints.s);
 	free(nut->syncpoints.pts);
+	free(nut->syncpoints.eor);
 
 	free_buffer(nut->tmp_buffer);
 	free_buffer(nut->o); // flushes file

Modified: trunk/libnut/priv.h
===================================================================
--- trunk/libnut/priv.h	2006-02-12 17:56:55 UTC (rev 62)
+++ trunk/libnut/priv.h	2006-02-24 07:31:25 UTC (rev 63)
@@ -83,6 +83,7 @@
 	int alloc_len;
 	syncpoint_t * s;
 	uint64_t * pts; // each elem is stream_count items, +1 to real pts, 0 means there is no key
+	uint64_t * eor; // same as pts, is the pts of last eor in syncpoint region _IF_ eor is set by syncpoint.
 } syncpoint_list_t;
 
 typedef struct {
@@ -100,7 +101,7 @@
 	int decode_delay;
 	nut_stream_header_t sh;
 	int64_t * pts_cache;
-	int eor;
+	int64_t eor;
 	// reorder.c
 	int64_t next_pts;
 	reorder_packet_t * packets;

Modified: trunk/nututils/demux_avi.c
===================================================================
--- trunk/nututils/demux_avi.c	2006-02-12 17:56:55 UTC (rev 62)
+++ trunk/nututils/demux_avi.c	2006-02-24 07:31:25 UTC (rev 63)
@@ -413,12 +413,13 @@
 
 	if (avi->cur >= avi->packets) return -1;
 
-	if ((avi->stream[0].last_pts % 100) < N && avi->buf) {
+	if ((avi->stream[0].last_pts % 1000) < N && avi->buf) {
 		p->next_pts = 0;
 		p->len = 5;
 		p->flags = NUT_KEY_STREAM_FLAG;
-		p->stream = 2 + (avi->stream[0].last_pts % 100);
+		p->stream = 2;//2 + (avi->stream[0].last_pts % 100);
 		p->pts = avi->stream[0].last_pts;
+		if (avi->stream[0].last_pts % 1000) p->flags |= NUT_EOR_STREAM_FLAG;
 		*buf = (void*)avi;
 		free(avi->buf);
 		avi->buf = NULL;




More information about the NUT-devel mailing list