[xiph-commits] r16683 - trunk/ffmpeg2theora/src
j at svn.xiph.org
j at svn.xiph.org
Fri Oct 30 22:40:08 PDT 2009
Author: j
Date: 2009-10-30 22:40:07 -0700 (Fri, 30 Oct 2009)
New Revision: 16683
Added:
trunk/ffmpeg2theora/src/index.c
trunk/ffmpeg2theora/src/index.h
Log:
actually add the index code, missing in last commit
Added: trunk/ffmpeg2theora/src/index.c
===================================================================
--- trunk/ffmpeg2theora/src/index.c (rev 0)
+++ trunk/ffmpeg2theora/src/index.c 2009-10-31 05:40:07 UTC (rev 16683)
@@ -0,0 +1,184 @@
+/* -*- tab-width:4;c-file-style:"cc-mode"; -*- */
+/*
+ * index.c -- Stores info about keyframes for indexing.
+ * Copyright (C) 2009 Mozilla Foundation.
+ *
+ * Contributed by Chris Pearce <chris at pearce.org.nz>.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <limits.h>
+#include <assert.h>
+#include "index.h"
+
+#include "theorautils.h"
+
+#ifndef INT64_MAX
+#define INT64_MAX (~((ogg_int64_t)1 << 63))
+#endif
+
+#ifndef INT64_MIN
+#define INT64_MIN ((ogg_int64_t)1 << 63)
+#endif
+
+
+void seek_index_init(seek_index* index, int packet_interval)
+{
+ if (!index)
+ return;
+ memset(index, 0, sizeof(seek_index));
+ index->prev_packet_time = INT64_MIN;
+ index->packet_interval = packet_interval;
+ index->start_time = INT64_MAX;
+ index->end_time = INT64_MIN;
+}
+
+void seek_index_clear(seek_index* index)
+{
+ if (!index)
+ return;
+ if (index->packet_capacity && index->packets) {
+ free(index->packets);
+ index->packets = 0;
+ index->packet_capacity = 0;
+ }
+ if (index->pages_capacity && index->pages) {
+ free(index->pages);
+ index->pages = 0;
+ index->pages_capacity = 0;
+ }
+}
+
+/*
+ * Ensures that |*pointer|, which points to |capacity| elements of size
+ * |element_size|, can contain |target_capacity| elements. This will realloc
+ * |*pointer| if necessary, updating |*capacity| when it does so.
+ * Returns 0 on success, -1 on failure (OOM).
+ */
+static int ensure_capacity(int* capacity,
+ int target_capacity,
+ size_t element_size,
+ void** pointer)
+{
+ size_t size = 0;
+ ogg_int64_t new_capacity;
+
+ if (*capacity > target_capacity) {
+ /* We have capacity to accommodate the increase. No need to resize. */
+ return 0;
+ }
+
+ /* Not enough capacity to accommodate increase, resize.
+ * Expand by 3/2 + 1. */
+ new_capacity = *capacity;
+ while (new_capacity >= 0 && new_capacity <= target_capacity) {
+ new_capacity = (new_capacity * 3) / 2 + 1;
+ }
+ if (new_capacity < 0 ||
+ new_capacity > INT_MAX ||
+ new_capacity * element_size > INT_MAX)
+ {
+ /* Integer overflow or otherwise ridiculous size. Fail. */
+ return -1;
+ }
+ size = (size_t)new_capacity * element_size;
+ *pointer = realloc(*pointer, size);
+ if (!*pointer) {
+ return -1;
+ }
+ *capacity = new_capacity;
+ return 0;
+}
+
+/*
+ * Returns 0 on success, -1 on failure.
+ */
+int seek_index_record_sample(seek_index* index,
+ int packetno,
+ ogg_int64_t start_time,
+ ogg_int64_t end_time,
+ int is_keyframe)
+{
+ keyframe_packet* packet;
+
+ /* Update the end/start times, so we know the extremes of the
+ indexed range. */
+ if (start_time < index->start_time) {
+ index->start_time = start_time;
+ }
+ if (end_time > index->end_time) {
+ index->end_time = end_time;
+ }
+
+ if (!is_keyframe ||
+ end_time < (index->prev_packet_time + index->packet_interval))
+ {
+ /* Sample is not a keyframe, or appears too close to the previous
+ keyframe packet, don't add it to the keyframe index. */
+ return 0;
+ }
+
+ if (ensure_capacity(&index->packet_capacity,
+ index->packet_num + 1,
+ sizeof(keyframe_packet),
+ (void**)&index->packets) != 0)
+ {
+ /* Can't increase array size, probably OOM. */
+ return -1;
+ }
+ packet = &index->packets[index->packet_num];
+ packet->packetno = packetno;
+ packet->start_time = start_time;
+ index->packet_num++;
+ index->prev_packet_time = start_time;
+
+ return 0;
+}
+
+/*
+ * 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)
+{
+ keyframe_page* page;
+ if (ensure_capacity(&index->pages_capacity,
+ index->pages_num + 1,
+ sizeof(keyframe_page),
+ (void**)&index->pages) != 0)
+ {
+ /* Can't increase array size, probably OOM. */
+ return -1;
+ }
+ page = &index->pages[index->pages_num];
+ page->offset = offset;
+ page->checksum = checksum;
+ page->packet_start_num = packet_start_num;
+ index->pages_num++;
+ return 0;
+}
+
+void seek_index_set_max_keypoints(seek_index* index, int max_keypoints)
+{
+ index->max_keypoints = max_keypoints;
+}
+
Added: trunk/ffmpeg2theora/src/index.h
===================================================================
--- trunk/ffmpeg2theora/src/index.h (rev 0)
+++ trunk/ffmpeg2theora/src/index.h 2009-10-31 05:40:07 UTC (rev 16683)
@@ -0,0 +1,121 @@
+/* -*- tab-width:4;c-file-style:"cc-mode"; -*- */
+/*
+ * index.h -- Stores info about keyframes for indexing.
+ * Copyright (C) 2009 Mozilla Foundation.
+ *
+ * Contributed by Chris Pearce <chris at pearce.org.nz>.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef __INDEX_H__
+#define __INDEX_H__
+
+#include <ogg/os_types.h>
+
+
+/* Records the packetno and end time of a keyframe's packet in an ogg
+ stream. */
+typedef struct {
+ int packetno;
+ ogg_int64_t start_time; /* in ms */
+}
+keyframe_packet;
+
+
+/* Records the geometry of pages in an ogg stream. From this we can reconstruct
+ the offset of the start of page in which any arbitrary packet starts. */
+typedef struct {
+
+ /* 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;
+}
+keyframe_page;
+
+/* Holds data relating to the keyframes in a stream, and the pages on which
+ the keyframes reside. */
+typedef struct {
+
+ /* Array of keyframe packets we've discovered in this stream. */
+ keyframe_packet* packets;
+ /* Numeber of allocated elements in |packets|. */
+ int packet_capacity;
+ /* Number of used elements in |packets|. */
+ int packet_num;
+
+ /* The end time of the previous keyframe packet added to the index. */
+ ogg_int64_t prev_packet_time;
+
+ /* Minimum time allowed between packets, in milliseconds. */
+ ogg_int64_t packet_interval;
+
+ /* Pages encoded into this stream. */
+ keyframe_page* pages;
+ /* Number of allocated elements in |pages|. */
+ int pages_capacity;
+ /* Number of used elements in |pages|. */
+ int pages_num;
+
+ /* Number of keypoints allocated in the placeholder index packet
+ on disk. */
+ int max_keypoints;
+
+ /* Byte offset of page which stores this index in the file. */
+ ogg_int64_t page_location;
+
+ /* The start time of the first sample in the stream, in ms. */
+ ogg_int64_t start_time;
+
+ /* The end time of the last sample in the stream, in ms. */
+ ogg_int64_t end_time;
+}
+seek_index;
+
+
+/* Initialize index to have a minimum of |packet_interval| ms between
+ keyframes. */
+void seek_index_init(seek_index* index, int packet_interval);
+
+/* Frees all memory associated with an index. */
+void seek_index_clear(seek_index* index);
+
+/* Records the packetno of a sample in an index, with corresponding
+ start and end times. Returns 0 on success, -1 on failure. */
+int seek_index_record_sample(seek_index* index,
+ int packetno,
+ ogg_int64_t start_time,
+ ogg_int64_t end_time,
+ int is_keyframe);
+
+/* 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
+ the size of the index packet, and its value can be estimated once the
+ media's duration is known. */
+void seek_index_set_max_keypoints(seek_index* index, int num_keypoints);
+
+
+#endif
More information about the commits
mailing list