Commit 6fb3f653 authored by Jan Gerber's avatar Jan Gerber
Browse files

actually add the index code, missing in last commit

parent 965dd276
/* -*- 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@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;
}
/* -*- 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@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
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment