/*****************************************************************************
* Copyright 2008. Pittsburgh Pattern Recognition, Inc.
*
* This file is part of the Frame Accurate Seeking extension library to
* ffmpeg (ffmpeg-fas).
*
* ffmpeg-fas is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 3 of the License, or (at your
* option) any later version.
*
* The ffmpeg-fas library 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 Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with the ffmpeg-fas library. If not, see .
*
******************************************************************************/
#include
#include
#include
#include
#include "seek_indices.h"
#include "private_errors.h"
/**** Defines *****************************************************************/
#define DEFAULT_INITIAL_SIZE 100
static seek_error_type private_show_error (const char *message, seek_error_type error);
static seek_error_type private_resize_table (seek_table_type *table, int new_size);
/*
* seek_init_table
*/
int compare_seek_tables(seek_table_type t1, seek_table_type t2)
{
int i;
// printf("n_entries=(%d %d)\n", t1.num_entries, t2.num_entries);
if (t1.num_entries != t2.num_entries)
return 0;
if (t1.completed != t2.completed)
return 0;
if (t1.num_frames != t2.num_frames)
return 0;
for (i=0;inum_entries = 0;
table->num_frames = -1;
table->completed = seek_false;
if (NULL == table || NULL == table->array)
return;
free (table->array);
return;
}
/*
* seek_copy_table
*/
seek_table_type seek_copy_table (seek_table_type source)
{
seek_table_type dest;
dest.num_entries = source.num_entries;
dest.num_frames = source.num_frames;
dest.completed = source.completed;
if (NULL == source.array)
{
dest.array = NULL;
dest.allocated_size = 0;
return dest;
}
dest.array = (seek_entry_type *)malloc (source.num_entries * sizeof(seek_entry_type));
if (NULL == dest.array)
{
dest.array = NULL;
dest.allocated_size = 0;
return dest;
}
dest.allocated_size = source.num_entries;
int i;
for (i=0;iarray)
return private_show_error("null or invalid seek table", seek_bad_argument);
if (table->num_entries != 0)
if (table->array[table->num_entries - 1].display_index >= entry.display_index)
return seek_no_error;
if (table->num_entries == table->allocated_size)
{
seek_error_type error = private_resize_table (table, table->num_entries * 2);
if (error != seek_no_error)
return private_show_error ("unable to resize seek table", error);
}
table->array[table->num_entries] = entry;
table->num_entries++;
return seek_no_error;
}
/*
* seek_get_nearest_entry
*/
seek_error_type seek_get_nearest_entry (seek_table_type *table, seek_entry_type *entry, int display_index, int offset)
{
/* using offset>0 returns a modified seek_entry that sets the 'time-to-seek' to be $offset keyframes in the past.
*/
if (NULL == table || NULL == table->array || table->num_entries <= 0) {
return private_show_error ("NULL or invalid seek table", seek_bad_argument);
}
if (NULL == entry) {
return private_show_error ("NULL entry buffer (for return)", seek_bad_argument);
}
if (display_index < table->array[0].display_index)
return private_show_error ("tried to seek to frame index before first frame", seek_bad_argument);
int i;
for (i=0; i < table->num_entries; i++)
if (table->array[i].display_index > display_index)
break;
i = i-1;
if (iarray[i];
(*entry).first_packet_dts = table->array[i-offset].first_packet_dts;
return seek_no_error;
}
/* read raw file */
seek_table_type read_table_file(char *name)
{
seek_table_type ans = { NULL, (seek_boolean_type) 0, (seek_boolean_type) 0 };
FILE *table_file = fopen(name, "r");
if (table_file == NULL)
return ans;
int completed_flag;
fscanf(table_file, "%d %d %d\n", &ans.num_frames, &ans.num_entries, &completed_flag);
if (completed_flag == 1)
ans.completed = seek_true;
else
ans.completed = seek_false;
ans.allocated_size = ans.num_entries;
ans.array = (seek_entry_type*) malloc (ans.allocated_size * sizeof(seek_entry_type));
int i;
for (i=0;idisplay_index, entry->first_packet_dts, entry->last_packet_dts);
}
return seek_no_error;
}
seek_error_type seek_show_table (seek_table_type table)
{
seek_entry_type *entry;
int index;
if (NULL == table.array || table.num_entries <= 0) {
return private_show_error ("NULL or invalid seek table", seek_bad_argument);
}
int completed_flag = 0;
if (table.completed == seek_true)
completed_flag = 1;
fprintf (stderr, "--- Seek Table Dump ---\n");
fprintf (stderr, "n_frames: %d n_entries: %d completed: %d\n",table.num_frames, table.num_entries, completed_flag);
for (index = 0; index < table.num_entries; index++)
{
entry = &(table.array[index]);
fprintf (stderr, " %04d --> %08lld (%08lld)\n", entry->display_index, entry->first_packet_dts, entry->last_packet_dts);
}
fprintf (stderr, "-----------------------\n");
return seek_no_error;
}
/*
* private_show_error
*/
static seek_error_type private_show_error (const char *message, seek_error_type error)
{
if (SHOW_ERROR_MESSAGES)
fprintf (stderr, " ===> seek_indices: %s\n", message);
return error;
}
/*
* private_resize_table
*/
static seek_error_type private_resize_table (seek_table_type *table, int new_size)
{
seek_entry_type *new_array = NULL;
if (table == NULL || new_size < 0) {
return private_show_error ("invalid argument for private_resize_table()", seek_malloc_failed);
}
new_array = (seek_entry_type *)malloc (sizeof (seek_entry_type) * new_size);
if (NULL == new_array) {
return private_show_error ("unable to allocate more space for table", seek_malloc_failed);
}
memcpy (new_array, table->array, table->allocated_size * sizeof (seek_entry_type));
free (table->array);
table->allocated_size = new_size;
table->array = new_array;
return seek_no_error;
}