mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
333 lines
9.8 KiB
Diff
333 lines
9.8 KiB
Diff
diff --git a/media/liboggz/include/oggz/oggz_seek.h b/media/liboggz/include/oggz/oggz_seek.h
|
|
--- a/media/liboggz/include/oggz/oggz_seek.h
|
|
+++ b/media/liboggz/include/oggz/oggz_seek.h
|
|
@@ -470,9 +470,28 @@ long oggz_seek_byorder (OGGZ * oggz, voi
|
|
* \param oggz An OGGZ handle previously opened for reading
|
|
* \param offset The offset of the start of data
|
|
* \returns 0 on success, -1 on failure.
|
|
*/
|
|
int oggz_set_data_start (OGGZ * oggz, oggz_off_t offset);
|
|
/** \}
|
|
*/
|
|
|
|
+/**
|
|
+ * Seeks Oggz to time unit_target, but with the bounds of the offset range
|
|
+ * [offset_begin, offset_end]. This is useful when seeking in network streams
|
|
+ * where only parts of a media are buffered, and retrieving unbuffered
|
|
+ * parts is expensive.
|
|
+ * \param oggz An OGGZ handle previously opened for reading
|
|
+ * \param unit_target The seek target, in milliseconds, or custom units
|
|
+ * \param offset_begin Start of offset range to seek inside, in bytes
|
|
+ * \param offset_end End of offset range to seek inside, in bytes,
|
|
+ pass -1 for end of media
|
|
+ * \returns The new position, in milliseconds or custom units
|
|
+ * \retval -1 on failure (unit_target is not within range)
|
|
+ */
|
|
+ogg_int64_t
|
|
+oggz_bounded_seek_set (OGGZ * oggz,
|
|
+ ogg_int64_t unit_target,
|
|
+ ogg_int64_t offset_begin,
|
|
+ ogg_int64_t offset_end);
|
|
+
|
|
#endif /* __OGGZ_SEEK_H__ */
|
|
diff --git a/media/liboggz/src/liboggz/oggz_seek.c b/media/liboggz/src/liboggz/oggz_seek.c
|
|
--- a/media/liboggz/src/liboggz/oggz_seek.c
|
|
+++ b/media/liboggz/src/liboggz/oggz_seek.c
|
|
@@ -617,205 +617,182 @@ oggz_offset_end (OGGZ * oggz)
|
|
if (oggz_io_seek (oggz, offset_save, SEEK_SET) == -1) {
|
|
return -1; /* fubar */
|
|
}
|
|
}
|
|
|
|
return offset_end;
|
|
}
|
|
|
|
-static ogg_int64_t
|
|
-oggz_seek_set (OGGZ * oggz, ogg_int64_t unit_target)
|
|
+ogg_int64_t
|
|
+oggz_bounded_seek_set (OGGZ * oggz,
|
|
+ ogg_int64_t unit_target,
|
|
+ ogg_int64_t offset_begin,
|
|
+ ogg_int64_t offset_end)
|
|
{
|
|
OggzReader * reader;
|
|
oggz_off_t offset_orig, offset_at, offset_guess;
|
|
- oggz_off_t offset_begin, offset_end = -1, offset_next;
|
|
+ oggz_off_t offset_next;
|
|
ogg_int64_t granule_at;
|
|
- ogg_int64_t unit_at, unit_begin = 0, unit_end = -1, unit_last_iter = -1;
|
|
+ ogg_int64_t unit_at, unit_begin = -1, unit_end = -1, unit_last_iter = -1;
|
|
long serialno;
|
|
ogg_page * og;
|
|
int hit_eof = 0;
|
|
|
|
if (oggz == NULL) {
|
|
return -1;
|
|
}
|
|
|
|
if (unit_target > 0 && !oggz_has_metrics (oggz)) {
|
|
#ifdef DEBUG
|
|
- printf ("oggz_seek_set: No metric defined, FAIL\n");
|
|
+ printf ("oggz_bounded_seek_set: No metric defined, FAIL\n");
|
|
#endif
|
|
return -1;
|
|
}
|
|
-
|
|
- if ((offset_end = oggz_offset_end (oggz)) == -1) {
|
|
+
|
|
+ if (offset_end == -1 && (offset_end = oggz_offset_end (oggz)) == -1) {
|
|
#ifdef DEBUG
|
|
- printf ("oggz_seek_set: oggz_offset_end == -1, FAIL\n");
|
|
+ printf ("oggz_bounded_seek_set: oggz_offset_end == -1, FAIL\n");
|
|
#endif
|
|
return -1;
|
|
}
|
|
|
|
reader = &oggz->x.reader;
|
|
|
|
if (unit_target == reader->current_unit) {
|
|
#ifdef DEBUG
|
|
- printf ("oggz_seek_set: unit_target == reader->current_unit, SKIP\n");
|
|
+ printf ("oggz_bounded_seek_set: unit_target == reader->current_unit, SKIP\n");
|
|
#endif
|
|
return (long)reader->current_unit;
|
|
}
|
|
|
|
if (unit_target == 0) {
|
|
offset_at = oggz_reset (oggz, oggz->offset_data_begin, 0, SEEK_SET);
|
|
if (offset_at == -1) return -1;
|
|
return 0;
|
|
}
|
|
|
|
offset_at = oggz_tell_raw (oggz);
|
|
if (offset_at == -1) return -1;
|
|
|
|
offset_orig = oggz->offset;
|
|
|
|
- offset_begin = 0;
|
|
-
|
|
unit_at = reader->current_unit;
|
|
- unit_begin = 0;
|
|
|
|
og = &oggz->current_page;
|
|
|
|
- if (oggz_seek_raw (oggz, 0, SEEK_END) >= 0) {
|
|
+ if (unit_end == -1 && oggz_seek_raw (oggz, offset_end, SEEK_SET) >= 0) {
|
|
ogg_int64_t granulepos;
|
|
|
|
if (oggz_get_prev_start_page (oggz, og, &granulepos, &serialno) >= 0) {
|
|
unit_end = oggz_get_unit (oggz, serialno, granulepos);
|
|
}
|
|
}
|
|
|
|
+ if (unit_begin == -1 && oggz_seek_raw (oggz, offset_begin, SEEK_SET) >= 0) {
|
|
+ ogg_int64_t granulepos;
|
|
+ if (oggz_get_next_start_page (oggz, og) >= 0) {
|
|
+ serialno = ogg_page_serialno (og);
|
|
+ granulepos = ogg_page_granulepos (og);
|
|
+ unit_begin = oggz_get_unit (oggz, serialno, granulepos);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /* Fail if target isn't in specified range. */
|
|
+ if (unit_target < unit_begin || unit_target > unit_end)
|
|
+ return -1;
|
|
+
|
|
+ /* Reduce the search range if possible using read cursor position. */
|
|
+ if (unit_at > unit_begin && unit_at < unit_end) {
|
|
+ if (unit_target < unit_at) {
|
|
+ unit_end = unit_at;
|
|
+ offset_end = offset_at;
|
|
+ } else {
|
|
+ unit_begin = unit_at;
|
|
+ offset_begin = offset_at;
|
|
+ }
|
|
+ }
|
|
+
|
|
og = &oggz->current_page;
|
|
|
|
for ( ; ; ) {
|
|
|
|
unit_last_iter = unit_at;
|
|
hit_eof = 0;
|
|
|
|
#ifdef DEBUG
|
|
- printf ("oggz_seek_set: [A] want u%lld: (u%lld - u%lld) [@%" PRI_OGGZ_OFF_T "d - @%" PRI_OGGZ_OFF_T "d]\n",
|
|
+ printf ("oggz_bounded_seek_set: [A] want u%lld: (u%lld - u%lld) [@%" PRI_OGGZ_OFF_T "d - @%" PRI_OGGZ_OFF_T "d]\n",
|
|
unit_target, unit_begin, unit_end, offset_begin, offset_end);
|
|
#endif
|
|
|
|
offset_guess = oggz_seek_guess (unit_at, unit_target,
|
|
unit_begin, unit_end,
|
|
offset_at,
|
|
offset_begin, offset_end);
|
|
if (offset_guess == -1) break;
|
|
|
|
if (offset_guess == offset_at) {
|
|
/* Already there, looping */
|
|
break;
|
|
}
|
|
|
|
if (offset_guess > offset_end) {
|
|
offset_guess = offset_end;
|
|
- }
|
|
-
|
|
- offset_at = oggz_seek_raw (oggz, offset_guess, SEEK_SET);
|
|
- if (offset_at == -1) {
|
|
- goto notfound;
|
|
- }
|
|
-
|
|
- offset_next = oggz_get_next_start_page (oggz, og);
|
|
-
|
|
-#ifdef DEBUG
|
|
- printf ("oggz_seek_set: offset_next %" PRI_OGGZ_OFF_T "d\n", offset_next);
|
|
-#endif
|
|
-
|
|
- if (/*unit_end == -1 &&*/ offset_next == -2) { /* reached eof, backtrack */
|
|
- hit_eof = 1;
|
|
- offset_next = oggz_get_prev_start_page (oggz, og, &granule_at,
|
|
- &serialno);
|
|
- unit_end = oggz_get_unit (oggz, serialno, granule_at);
|
|
-#ifdef DEBUG
|
|
- printf ("oggz_seek_set: [C] offset_next @%" PRI_OGGZ_OFF_T "d, g%lld, (s%ld)\n",
|
|
- offset_next, granule_at, serialno);
|
|
- printf ("oggz_seek_set: [c] u%lld\n",
|
|
- oggz_get_unit (oggz, serialno, granule_at));
|
|
-#endif
|
|
- } else if (offset_next >= 0) {
|
|
+ offset_at = oggz_seek_raw (oggz, offset_guess, SEEK_SET);
|
|
+ offset_next = oggz_get_prev_start_page (oggz, og, &granule_at, &serialno);
|
|
+ } else {
|
|
+ offset_at = oggz_seek_raw (oggz, offset_guess, SEEK_SET);
|
|
+ offset_next = oggz_get_next_start_page (oggz, og);
|
|
serialno = ogg_page_serialno (og);
|
|
granule_at = ogg_page_granulepos (og);
|
|
}
|
|
|
|
- if (offset_next < 0) {
|
|
- goto notfound;
|
|
- }
|
|
-
|
|
- if (hit_eof || offset_next > offset_end) {
|
|
- offset_next =
|
|
- oggz_scan_for_page (oggz, og, unit_target, offset_begin, offset_end);
|
|
- if (offset_next < 0) goto notfound;
|
|
-
|
|
- offset_at = offset_next;
|
|
- serialno = ogg_page_serialno (og);
|
|
- granule_at = ogg_page_granulepos (og);
|
|
-
|
|
- unit_at = oggz_get_unit (oggz, serialno, granule_at);
|
|
-
|
|
- goto found;
|
|
- }
|
|
-
|
|
- offset_at = offset_next;
|
|
-
|
|
unit_at = oggz_get_unit (oggz, serialno, granule_at);
|
|
|
|
+#ifdef DEBUG
|
|
+ printf ("oggz_bounded_seek_set: offset_next %" PRI_OGGZ_OFF_T "d\n", offset_next);
|
|
+#endif
|
|
if (unit_at == unit_last_iter) break;
|
|
|
|
#ifdef DEBUG
|
|
- printf ("oggz_seek_set: [D] want u%lld, got page u%lld @%" PRI_OGGZ_OFF_T "d g%lld\n",
|
|
+ printf ("oggz_bounded_seek_set: [D] want u%lld, got page u%lld @%" PRI_OGGZ_OFF_T "d g%lld\n",
|
|
unit_target, unit_at, offset_at, granule_at);
|
|
#endif
|
|
|
|
if (unit_at < unit_target) {
|
|
offset_begin = offset_at;
|
|
unit_begin = unit_at;
|
|
if (unit_end == unit_begin) break;
|
|
} else if (unit_at > unit_target) {
|
|
offset_end = offset_at-1;
|
|
unit_end = unit_at;
|
|
if (unit_end == unit_begin) break;
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
|
|
- found:
|
|
do {
|
|
offset_at = oggz_get_prev_start_page (oggz, og, &granule_at, &serialno);
|
|
unit_at = oggz_get_unit (oggz, serialno, granule_at);
|
|
} while (unit_at > unit_target);
|
|
|
|
if (offset_at < 0) {
|
|
oggz_reset (oggz, offset_orig, -1, SEEK_SET);
|
|
return -1;
|
|
}
|
|
|
|
offset_at = oggz_reset (oggz, offset_at, unit_at, SEEK_SET);
|
|
if (offset_at == -1) return -1;
|
|
|
|
#ifdef DEBUG
|
|
- printf ("oggz_seek_set: FOUND (%lld)\n", unit_at);
|
|
+ printf ("oggz_bounded_seek_set: FOUND (%lld)\n", unit_at);
|
|
#endif
|
|
|
|
return (long)reader->current_unit;
|
|
-
|
|
- notfound:
|
|
-#ifdef DEBUG
|
|
- printf ("oggz_seek_set: NOT FOUND\n");
|
|
-#endif
|
|
-
|
|
- oggz_reset (oggz, offset_orig, -1, SEEK_SET);
|
|
-
|
|
- return -1;
|
|
}
|
|
|
|
static ogg_int64_t
|
|
oggz_seek_end (OGGZ * oggz, ogg_int64_t unit_offset)
|
|
{
|
|
oggz_off_t offset_orig, offset_at, offset_end;
|
|
ogg_int64_t granulepos;
|
|
ogg_int64_t unit_end;
|
|
@@ -838,17 +815,17 @@ oggz_seek_end (OGGZ * oggz, ogg_int64_t
|
|
return -1;
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
printf ("*** oggz_seek_end: found packet (%lld) at @%" PRI_OGGZ_OFF_T "d [%lld]\n",
|
|
unit_end, offset_end, granulepos);
|
|
#endif
|
|
|
|
- return oggz_seek_set (oggz, unit_end + unit_offset);
|
|
+ return oggz_bounded_seek_set (oggz, unit_end + unit_offset, 0, -1);
|
|
}
|
|
|
|
off_t
|
|
oggz_seek (OGGZ * oggz, oggz_off_t offset, int whence)
|
|
{
|
|
OggzReader * reader;
|
|
ogg_int64_t units = -1;
|
|
|
|
@@ -897,21 +874,21 @@ oggz_seek_units (OGGZ * oggz, ogg_int64_
|
|
#endif
|
|
return -1;
|
|
}
|
|
|
|
reader = &oggz->x.reader;
|
|
|
|
switch (whence) {
|
|
case SEEK_SET:
|
|
- r = oggz_seek_set (oggz, units);
|
|
+ r = oggz_bounded_seek_set (oggz, units, 0, -1);
|
|
break;
|
|
case SEEK_CUR:
|
|
units += reader->current_unit;
|
|
- r = oggz_seek_set (oggz, units);
|
|
+ r = oggz_bounded_seek_set (oggz, units, 0, -1);
|
|
break;
|
|
case SEEK_END:
|
|
r = oggz_seek_end (oggz, units);
|
|
break;
|
|
default:
|
|
/*oggz_set_error (oggz, OGGZ_EINVALID);*/
|
|
r = -1;
|
|
break;
|