[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