
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;
participants (1)
-
ods15@natsuki.mplayerhq.hu