[xiph-commits] r16837 - trunk/ffmpeg2theora/src
j at svn.xiph.org
j at svn.xiph.org
Wed Jan 27 21:55:38 PST 2010
Author: j
Date: 2010-01-27 21:55:38 -0800 (Wed, 27 Jan 2010)
New Revision: 16837
Modified:
trunk/ffmpeg2theora/src/ffmpeg2theora.c
trunk/ffmpeg2theora/src/index.c
trunk/ffmpeg2theora/src/index.h
trunk/ffmpeg2theora/src/theorautils.c
trunk/ffmpeg2theora/src/theorautils.h
Log:
update index to Skeleton 3.3
Modified: trunk/ffmpeg2theora/src/ffmpeg2theora.c
===================================================================
--- trunk/ffmpeg2theora/src/ffmpeg2theora.c 2010-01-27 12:23:43 UTC (rev 16836)
+++ trunk/ffmpeg2theora/src/ffmpeg2theora.c 2010-01-28 05:55:38 UTC (rev 16837)
@@ -87,6 +87,8 @@
NOSKELETON,
SEEK_INDEX,
INDEX_INTERVAL,
+ THEORA_INDEX_RESERVE,
+ VORBIS_INDEX_RESERVE,
INFO_FLAG
} F2T_FLAGS;
@@ -1827,7 +1829,6 @@
" -o, --output alternative output filename\n"
" --no-skeleton disables ogg skeleton metadata output\n"
" --seek-index enables keyframe index in skeleton track\n"
- " --index-interval set minimum distance between indexed keyframes (in ms, default: 2000)\n"
" -s, --starttime start encoding at this time (in sec.)\n"
" -e, --endtime end encoding at this time (in sec.)\n"
" -p, --preset encode file with preset.\n"
@@ -1950,6 +1951,12 @@
" --nometadata disables metadata from input\n"
" --no-oshash do not include oshash of source file(SOURCE_OSHASH)\n"
"\n"
+ "Keyframe indexing options:\n"
+ " --index-interval <n> set minimum distance between indexed keyframes\n"
+ " to <n> ms (default: 2000)\n"
+ " --theora-index-reserve <n> reserve <n> bytes for theora keyframe index\n"
+ " --vorbis-index-reserve <n> reserve <n> bytes for vorbis keyframe indes\n"
+ "\n"
"Other options:\n"
#ifndef _WIN32
" --nice n set niceness to n\n"
@@ -2008,6 +2015,8 @@
{"no-skeleton",no_argument,&flag,NOSKELETON},
{"seek-index",no_argument,&flag,SEEK_INDEX},
{"index-interval",required_argument,&flag,INDEX_INTERVAL},
+ {"theora-index-reserve",required_argument,&flag,THEORA_INDEX_RESERVE},
+ {"vorbis-index-reserve",required_argument,&flag,VORBIS_INDEX_RESERVE},
{"format",required_argument,NULL,'f'},
{"width",required_argument,NULL,'x'},
{"height",required_argument,NULL,'y'},
@@ -2259,6 +2268,14 @@
info.index_interval = atoi(optarg);
flag = -1;
break;
+ case THEORA_INDEX_RESERVE:
+ info.theora_index_reserve = atoi(optarg);
+ flag = -1;
+ break;
+ case VORBIS_INDEX_RESERVE:
+ info.vorbis_index_reserve = atoi(optarg);
+ flag = -1;
+ break;
case INFO_FLAG:
output_json = 1;
break;
Modified: trunk/ffmpeg2theora/src/index.c
===================================================================
--- trunk/ffmpeg2theora/src/index.c 2010-01-27 12:23:43 UTC (rev 16836)
+++ trunk/ffmpeg2theora/src/index.c 2010-01-28 05:55:38 UTC (rev 16837)
@@ -46,6 +46,7 @@
index->packet_interval = packet_interval;
index->start_time = INT64_MAX;
index->end_time = INT64_MIN;
+ index->packet_size = -1;
}
void seek_index_clear(seek_index* index)
@@ -152,7 +153,6 @@
*/
int seek_index_record_page(seek_index* index,
ogg_int64_t offset,
- ogg_uint32_t checksum,
int packet_start_num)
{
keyframe_page* page;
@@ -166,7 +166,6 @@
}
page = &index->pages[index->pages_num];
page->offset = offset;
- page->checksum = checksum;
page->packet_start_num = packet_start_num;
index->pages_num++;
return 0;
Modified: trunk/ffmpeg2theora/src/index.h
===================================================================
--- trunk/ffmpeg2theora/src/index.h 2010-01-27 12:23:43 UTC (rev 16836)
+++ trunk/ffmpeg2theora/src/index.h 2010-01-28 05:55:38 UTC (rev 16837)
@@ -41,9 +41,6 @@
/* Byte offset of the start of the page. */
ogg_int64_t offset;
- /* Checksum of this page. */
- ogg_uint32_t checksum;
-
/* Number of packets that start on this page. */
int packet_start_num;
}
@@ -85,6 +82,9 @@
/* The end time of the last sample in the stream, in ms. */
ogg_int64_t end_time;
+
+ /* The size we'll reserve for the index packet on disk. */
+ unsigned int packet_size;
}
seek_index;
@@ -107,7 +107,6 @@
/* Returns 0 on success, -1 on failure. */
int seek_index_record_page(seek_index* index,
ogg_int64_t offset,
- ogg_uint32_t checksum,
int packet_start_num);
/* Sets maximum number of keypoints we'll allowe in an index. This sets
Modified: trunk/ffmpeg2theora/src/theorautils.c
===================================================================
--- trunk/ffmpeg2theora/src/theorautils.c 2010-01-27 12:23:43 UTC (rev 16836)
+++ trunk/ffmpeg2theora/src/theorautils.c 2010-01-28 05:55:38 UTC (rev 16837)
@@ -64,6 +64,8 @@
info->with_skeleton = 1; /* skeleton is enabled by default */
info->with_seek_index = 0; /* keyframe index disabled by default. */
info->index_interval = 2000;
+ info->theora_index_reserve = -1;
+ info->vorbis_index_reserve = -1;
info->indexing_complete = 0;
info->frontend = NULL; /*frontend mode*/
info->videotime = 0;
@@ -242,13 +244,13 @@
ogg_uint32_t version = SKELETON_VERSION(ver_maj, ver_min);
assert(version >= SKELETON_VERSION(3,0) ||
- version <= SKELETON_VERSION(3,2));
+ version <= SKELETON_VERSION(3,3));
switch (version) {
case SKELETON_VERSION(3,0):
packet_size = 64;
break;
- case SKELETON_VERSION(3,2):
+ case SKELETON_VERSION(3,3):
packet_size = 112;
break;
default:
@@ -389,12 +391,13 @@
return !keypoints_per_second ? 0 : ((int)ceil(duration / keypoints_per_second) + 2);
}
-static int create_index_packet(int num_allocated_keypoints,
+/* Creates a new index packet, with |bytes| space set aside for index. */
+static int create_index_packet(size_t bytes,
ogg_packet* op,
ogg_uint32_t serialno,
ogg_int64_t num_used_keypoints)
{
- size_t size = 26 + num_allocated_keypoints * KEYPOINT_SIZE;
+ size_t size = 26 + bytes;
memset (op, 0, sizeof(*op));
op->packet = malloc(size);
if (op->packet == NULL)
@@ -428,9 +431,16 @@
{
ogg_packet op;
ogg_page og;
- int num_keypoints = keypoints_per_index(&info->theora_index,
+ int num_keypoints = keypoints_per_index(index,
info->duration);
- if (create_index_packet(num_keypoints, &op, serialno, 0) == -1) {
+ if (index->packet_size == -1) {
+ index->packet_size = (int)(num_keypoints * 5.1);
+ }
+ if (create_index_packet(index->packet_size,
+ &op,
+ serialno,
+ 0) == -1)
+ {
return -1;
}
@@ -454,15 +464,54 @@
return 0;
}
+/* Counts number of bytes required to encode n with variable byte encoding. */
+static int bytes_required(ogg_int64_t n) {
+ int bits = 0;
+ int bytes = 0;
+ assert(n >= 0);
+ /* Determine number of bits required. */
+ while (n) {
+ n = n >> 1;
+ bits++;
+ }
+ /* 7 bits per byte, plus 1 if we spill over onto the next byte. */
+ bytes = bits / 7;
+ return bytes + (((bits % 7) != 0 || bits == 0) ? 1 : 0);
+}
+
+static unsigned char*
+write_vl_int(unsigned char* p, const unsigned char* limit, ogg_int64_t n)
+{
+ ogg_int64_t k = n;
+ unsigned char* x = p;
+ assert(n >= 0);
+ do {
+ if (p >= limit) {
+ return p;
+ }
+ unsigned char b = (unsigned char)(k & 0x7f);
+ k >>= 7;
+ if (k == 0) {
+ // Last byte, add terminating bit.
+ b |= 0x80;
+ }
+ *p = b;
+ p++;
+ } while (k && p < limit);
+ assert(x + bytes_required(n) == p);
+
+ return p;
+}
+
typedef struct {
ogg_int64_t offset;
- ogg_uint32_t checksum;
ogg_int64_t time;
} keypoint;
/* Overwrites pages on disk for a stream's index with actual index data. */
static int
write_index_pages (seek_index* index,
+ const char* name,
oggmux_info *info,
ogg_uint32_t serialno,
int target_packet)
@@ -480,6 +529,12 @@
int prev_keyframe_pageno = -INT_MAX;
ogg_int64_t prev_keyframe_start_time = -INT_MAX;
int packet_in_page = 0;
+ unsigned char* p = 0;
+ ogg_int64_t prev_offset = 0;
+ ogg_int64_t prev_time = 0;
+ const unsigned char* limit = 0;
+ int index_bytes = 0;
+ int keypoints_cutoff = 0;
/* Must have indexed keypoints. */
assert(index->max_keypoints > 0 && index->packet_num > 0);
@@ -496,6 +551,8 @@
}
memset(keypoints, -1, sizeof(keypoint) * num_keypoints);
+ prev_offset = 0;
+ prev_time = 0;
for (i=0; i < index->packet_num && k < num_keypoints; i++) {
packetno = index->packets[i].packetno;
/* Increment pageno until we find the page which contains the start of
@@ -526,25 +583,58 @@
/* Add to final keyframe index. */
keypoints[k].offset = index->pages[pageno].offset;
- keypoints[k].checksum = index->pages[pageno].checksum;
keypoints[k].time = index->packets[i].start_time;
+
+ /* Count how many bytes is required to encode this keypoint. */
+ index_bytes += bytes_required(keypoints[k].offset - prev_offset);
+ prev_offset = keypoints[k].offset;
+ index_bytes += bytes_required(keypoints[k].time - prev_time);
+ prev_time = keypoints[k].time;
+
k++;
+
+ if (index_bytes < index->packet_size) {
+ keypoints_cutoff = k;
+ }
+
prev_keyframe_start_time = index->packets[i].start_time;
}
- num_keypoints = k;
+ if (index_bytes > index->packet_size) {
+ printf("WARNING: Underestimated space for %s keyframe index, dropped %d keyframes, "
+ "only part of the file may be indexed. Rerun with --%s-index-reserve %d to "
+ "ensure a complete index, or use OggIndex to re-index.\n",
+ name, (k - keypoints_cutoff), name, index_bytes);
+ } else if (index_bytes < index->packet_size) {
+ printf("Allocated %d bytes for %s keyframe index, %d are unused. "
+ "Rerun with '--%s-index-reserve %d' to encode with the optimal sized %s index,"
+ " or use OggIndex to re-index.\n",
+ index->packet_size, name, (index->packet_size - index_bytes),
+ name, index_bytes, name);
+ }
+ num_keypoints = keypoints_cutoff;
- if (create_index_packet(index->max_keypoints, &op, serialno, num_keypoints) == -1) {
+ if (create_index_packet(index->packet_size,
+ &op,
+ serialno,
+ num_keypoints) == -1)
+ {
free(keypoints);
return -1;
}
/* Write keypoint data into packet. */
+ p = op.packet + 26;
+ limit = op.packet + op.bytes;
+ prev_offset = 0;
+ prev_time = 0;
for (i=0; i<num_keypoints; i++) {
- unsigned char* p = op.packet + 26 + i * KEYPOINT_SIZE;
keypoint* k = &keypoints[i];
- write64le(p, k->offset);
- write32le(p+8, k->checksum);
- write64le(p+12, k->time);
+ ogg_int64_t offset_diff = k->offset - prev_offset;
+ ogg_int64_t time_diff = k->time - prev_time;
+ p = write_vl_int(p, limit, offset_diff);
+ p = write_vl_int(p, limit, time_diff);
+ prev_offset = k->offset;
+ prev_time = k->time;
}
free(keypoints);
@@ -596,7 +686,7 @@
ogg_stream_clear(&info->so);
ogg_stream_init(&info->so, serialno);
- add_fishead_packet (info, 3, 2);
+ add_fishead_packet (info, 3, 3);
if (ogg_stream_flush(&info->so, &og) != 1) {
fprintf (stderr, "Internal Ogg library error.\n");
exit (1);
@@ -623,8 +713,11 @@
break;
}
+ /* Write a new line, so that when we print out indexing stats, it's on a new line. */
+ printf("\n");
if (!info->audio_only &&
write_index_pages(&info->theora_index,
+ "theora",
info,
info->to.serialno,
1) == -1)
@@ -633,6 +726,7 @@
}
if (!info->video_only &&
write_index_pages(&info->vorbis_index,
+ "vorbis",
info,
info->vo.serialno,
2) == -1)
@@ -655,6 +749,9 @@
after encode when we add the index. */
static int write_placeholder_index_pages (oggmux_info *info)
{
+ if (info->theora_index_reserve != -1) {
+ info->theora_index.packet_size = info->theora_index_reserve;
+ }
if (!info->audio_only &&
write_index_placeholder_for_stream(info,
&info->theora_index,
@@ -662,6 +759,9 @@
{
return -1;
}
+ if (info->vorbis_index_reserve != -1) {
+ info->vorbis_index.packet_size = info->vorbis_index_reserve;
+ }
if (!info->video_only &&
write_index_placeholder_for_stream(info,
&info->vorbis_index,
@@ -796,7 +896,7 @@
}
ogg_stream_clear (&info->so);
ogg_stream_init (&info->so, rand());
- add_fishead_packet (info, 3, 2);
+ add_fishead_packet (info, 3, 3);
if (ogg_stream_pageout (&info->so, &og) != 1) {
fprintf (stderr, "Internal Ogg library error.\n");
exit (1);
@@ -1336,7 +1436,6 @@
ret = seek_index_record_page(&info->vorbis_index,
page_offset,
- checksum,
packet_start_num);
assert(ret == 0);
#ifdef OGGMUX_DEBUG
@@ -1371,7 +1470,6 @@
ret = seek_index_record_page(&info->theora_index,
page_offset,
- checksum,
packet_start_num);
assert(ret == 0);
#ifdef OGGMUX_DEBUG
Modified: trunk/ffmpeg2theora/src/theorautils.h
===================================================================
--- trunk/ffmpeg2theora/src/theorautils.h 2010-01-27 12:23:43 UTC (rev 16836)
+++ trunk/ffmpeg2theora/src/theorautils.h 2010-01-28 05:55:38 UTC (rev 16837)
@@ -76,6 +76,8 @@
int with_skeleton;
int with_seek_index;
int index_interval;
+ int theora_index_reserve;
+ int vorbis_index_reserve;
int indexing_complete;
FILE *frontend;
/* vorbis settings */
@@ -149,6 +151,7 @@
seek_index vorbis_index;
int prev_vorbis_window; /* Window size of previous vorbis block. Used to
calculate duration of vorbis packets. */
+ /* The offset of the first non header page in bytes. */
ogg_int64_t content_offset;
}
oggmux_info;
More information about the commits
mailing list