summaryrefslogtreecommitdiff
path: root/rotord/src
diff options
context:
space:
mode:
authorTim Redfern <tim@eclectronics.org>2013-09-11 16:11:47 +0100
committerTim Redfern <tim@eclectronics.org>2013-09-11 16:11:47 +0100
commitf9694b7d4f1648a0fa984e7cc428bbc9eea86ca0 (patch)
tree59e14e57c52e82927963ef71bf83de0f665c42cb /rotord/src
parent1f52520db005e056e131f511418e4b71bc9e89fd (diff)
ffms2 library for video loader
Diffstat (limited to 'rotord/src')
-rw-r--r--rotord/src/ffmpeg-fas_wrapper.cpp1
-rw-r--r--rotord/src/ffmpeg-fas_wrapper.h16
-rw-r--r--rotord/src/ffmpeg_fas.c948
-rw-r--r--rotord/src/ffmpeg_fas.h130
-rw-r--r--rotord/src/graph.cpp2
-rw-r--r--rotord/src/graph.h1
-rw-r--r--rotord/src/libavwrapper.cpp60
-rw-r--r--rotord/src/libavwrapper.h64
-rw-r--r--rotord/src/ofUtils.obin0 -> 593072 bytes
-rw-r--r--rotord/src/private_errors.h32
-rw-r--r--rotord/src/rendercontext.h1
-rw-r--r--rotord/src/rotor.cpp4
-rw-r--r--rotord/src/rotor.h71
-rw-r--r--rotord/src/seek_indices.c319
-rw-r--r--rotord/src/seek_indices.h94
15 files changed, 190 insertions, 1553 deletions
diff --git a/rotord/src/ffmpeg-fas_wrapper.cpp b/rotord/src/ffmpeg-fas_wrapper.cpp
deleted file mode 100644
index f1b81c2..0000000
--- a/rotord/src/ffmpeg-fas_wrapper.cpp
+++ /dev/null
@@ -1 +0,0 @@
-#include "ffmpeg-fas_wrapper.h"
diff --git a/rotord/src/ffmpeg-fas_wrapper.h b/rotord/src/ffmpeg-fas_wrapper.h
deleted file mode 100644
index dedff62..0000000
--- a/rotord/src/ffmpeg-fas_wrapper.h
+++ /dev/null
@@ -1,16 +0,0 @@
-#ifndef ffmpeg_fas_wrapper_H
-#define ffmpeg_fas_wrapper_H
-
-#include <string>
-#include "ffmpeg_fas.h"
-
-
-namespace ffmpeg_fas {
- class decoder
- {
- public:
- bool open(std::string& fileName);
- fas_raw_image_type frame;
- };
-}
-#endif
diff --git a/rotord/src/ffmpeg_fas.c b/rotord/src/ffmpeg_fas.c
deleted file mode 100644
index 19e9655..0000000
--- a/rotord/src/ffmpeg_fas.c
+++ /dev/null
@@ -1,948 +0,0 @@
-/*****************************************************************************
- * 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 <http://www.gnu.org/licenses/>.
- *
- ******************************************************************************/
-
-#include "ffmpeg_fas.h"
-
-#if defined( _WIN32 ) && defined( STATIC_DLL )
-extern "C"
-{
- #include "libavformat/avformat.h"
- #include "libavcodec/avcodec.h"
- //int img_convert(AVPicture *dst, int dst_pix_fmt, const AVPicture *src, int src_pix_fmt, int src_width, int src_height);
-}
-#else
-#include "libavformat/avformat.h"
-#include "libavcodec/avcodec.h"
-#endif /* _WIN32 && STATIC_DLL */
-
-#include "seek_indices.h"
-#include "private_errors.h"
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <stdint.h>
-#include <string.h>
-
-#define FIRST_FRAME_INDEX 0
-#define NUM_POSSIBLE_ERRORS 9
-
-enum PixelFormat fmt;
-
-/**** Private Types ***********************************************************/
-
-typedef struct fas_context_struct {
- fas_boolean_type is_video_active;
- fas_boolean_type is_frame_available;
-
- int current_frame_index;
-
- seek_table_type seek_table;
-
- /* ffmpeg */
- AVFormatContext *format_context;
- AVCodecContext *codec_context;
- int stream_idx;
-
- AVFrame *frame_buffer; // internal buffer
-
- AVFrame *rgb_frame_buffer; // extra AVFrames (for color conversion)
- uint8_t *rgb_buffer; // actual data buffer for rgb_frame_buffer (needs to be freed seperately)
- fas_boolean_type rgb_already_converted; // color_convert(frame_buffer) == rgb_frame_buffer (so we don't need to repeat conversions)
-
- AVFrame *gray8_frame_buffer;
- uint8_t *gray8_buffer;
- fas_boolean_type gray8_already_converted;
-
- int64_t current_dts; // decoding timestamp of the most recently parsed packet
- int64_t previous_dts; // for previous packet (always use previous packet for seek_table (workaround))
- int64_t keyframe_packet_dts; // dts of most recent keyframe packet
- int64_t first_dts; // for very first packet (needed in seek, for first keyframe)
-
-} fas_context_type;
-
-static char* invalid_error_code = "not a valid error code";
-static char *gbl_error_strings[NUM_POSSIBLE_ERRORS] =
-{
- "fas_success",
- "fas_failure",
- "fas_invalid_argument",
- "fas_out_of_memory",
- "fas_unsupported_format",
- "fas_unsupported_codec",
- "fas_no_more_frames",
- "fas_decoding_error",
- "fas_seek_error"
-};
-
-char* fas_error_message(fas_error_type error)
-{
- if ((error < 0) || (error >= NUM_POSSIBLE_ERRORS))
- return invalid_error_code;
-
- return gbl_error_strings[error];
-}
-
-void private_show_warning (const char *message);
-fas_error_type private_show_error (const char *message, fas_error_type error);
-fas_error_type private_convert_to_rgb (fas_context_ref_type ctx);
-fas_error_type private_seek_to_nearest_key (fas_context_ref_type context, int target_index, int offset);
-fas_error_type private_complete_seek_table (fas_context_ref_type context);
-
-
-void fas_set_logging (fas_boolean_type logging)
-{
- if (logging == FAS_TRUE)
- {
- SHOW_ERROR_MESSAGES = 1;
- SHOW_WARNING_MESSAGES = 1;
-#ifndef _WIN32
- av_log_set_level(AV_LOG_INFO); //TJR 080913
-#endif
- }
- else
- {
- SHOW_ERROR_MESSAGES = 0;
- SHOW_WARNING_MESSAGES = 0;
-#ifndef _WIN32
- av_log_set_level(AV_LOG_QUIET); //TJR 080913
-#endif
- }
-}
-
-/* Set the output image colorspace */
-void fas_set_format(fas_color_space_type format)
-{
- switch (format)
- {
- case FAS_GRAY8:
- fmt = PIX_FMT_GRAY8;
- break;
- case FAS_ARGB32:
- fmt = PIX_FMT_RGB32_1;
- break;
- case FAS_ABGR32:
- fmt = PIX_FMT_BGR32_1;
- break;
- case FAS_YUV420P:
- fmt = PIX_FMT_YUV420P;
- break;
- case FAS_YUYV422:
- fmt = PIX_FMT_YUYV422;
- break;
- case FAS_UYVY422:
- fmt = PIX_FMT_UYVY422;
- break;
- case FAS_YUV422P:
- fmt = PIX_FMT_YUV422P;
- break;
- case FAS_YUV444P:
- fmt = PIX_FMT_YUV444P;
- break;
- case FAS_RGB24:
- fmt = PIX_FMT_RGB24;
- break;
- case FAS_BGR24:
- fmt = PIX_FMT_BGR24;
- break;
- default:
- fmt = PIX_FMT_RGB24;
- break;
- }
-}
-
-
-void fas_initialize (fas_boolean_type logging, fas_color_space_type format)
-{
- fas_set_logging(logging);
- fas_set_format(format);
- av_register_all();
-
- return;
-}
-
-/* fas_open_video */
-
-fas_error_type fas_open_video (fas_context_ref_type *context_ptr, char *file_path)
-{
- if (NULL == context_ptr)
- return private_show_error ("NULL context pointer provided", FAS_INVALID_ARGUMENT);
-
- // seek_error_type seek_error;
- fas_context_ref_type fas_context;
-
- *context_ptr = NULL; // set returned context to NULL in case of error
-
- fas_context = (fas_context_ref_type)malloc (sizeof (fas_context_type));
- memset(fas_context, 0, sizeof(fas_context_type));
-
- if (NULL == fas_context)
- return private_show_error ("unable to allocate buffer", FAS_OUT_OF_MEMORY);
-
- fas_context->is_video_active = FAS_TRUE;
- fas_context->is_frame_available = FAS_TRUE;
- fas_context->current_frame_index = FIRST_FRAME_INDEX - 1;
- fas_context->current_dts = AV_NOPTS_VALUE;
- fas_context->previous_dts = AV_NOPTS_VALUE;
- fas_context->keyframe_packet_dts = AV_NOPTS_VALUE;
- fas_context->first_dts = AV_NOPTS_VALUE;
-
- fas_context->seek_table = seek_init_table (-1); /* default starting size */
-
- if (avformat_open_input( &(fas_context->format_context), file_path, NULL, NULL ) != 0) //TJR updated from av_open_file 080913
- {
- fas_close_video(fas_context);
- return private_show_error ("failure to open file", FAS_UNSUPPORTED_FORMAT);
- }
-
- if (avformat_find_stream_info (fas_context->format_context,NULL) < 0) //TJR updated from av_find_stream_info 080913
- {
- fas_close_video(fas_context);
- return private_show_error ("could not extract stream information", FAS_UNSUPPORTED_FORMAT);
- }
-
- if (SHOW_WARNING_MESSAGES)
- av_dump_format(fas_context->format_context, 0, file_path, 0);
-
- int stream_idx;
- for (stream_idx = 0; stream_idx < fas_context->format_context->nb_streams; stream_idx++)
- {
- if (fas_context->format_context->streams[stream_idx]->codec->codec_type == AVMEDIA_TYPE_VIDEO)
- {
- fas_context->stream_idx = stream_idx;
- fas_context->codec_context = fas_context->format_context->streams[stream_idx]->codec;
- break;
- }
- }
-
- if (fas_context->codec_context == 0)
- {
- fas_close_video(fas_context);
- return private_show_error ("failure to find a video stream", FAS_UNSUPPORTED_FORMAT);
- }
-
- AVCodec *codec = avcodec_find_decoder (fas_context->codec_context->codec_id);
-
- if (!codec)
- {
- fas_context->codec_context = 0;
- fas_close_video(fas_context);
- return private_show_error("failed to find correct video codec", FAS_UNSUPPORTED_CODEC);
- }
-
- if (avcodec_open2(fas_context->codec_context, codec,NULL) < 0) //TJR 080913 added NULL options dictionary
- {
- fas_context->codec_context = 0;
- fas_close_video(fas_context);
- return private_show_error ("failed to open codec", FAS_UNSUPPORTED_CODEC);
- }
-
- fas_context->frame_buffer = avcodec_alloc_frame ();
- if (fas_context->frame_buffer == NULL)
- {
- fas_close_video(fas_context);
- return private_show_error ("failed to allocate frame buffer", FAS_OUT_OF_MEMORY);
- }
-
- fas_context->rgb_frame_buffer = avcodec_alloc_frame ();
- if (fas_context->rgb_frame_buffer == NULL)
- {
- fas_close_video(fas_context);
- return private_show_error ("failed to allocate rgb frame buffer", FAS_OUT_OF_MEMORY);
- }
-
- fas_context->gray8_frame_buffer = avcodec_alloc_frame ();
- if (fas_context->gray8_frame_buffer == NULL)
- {
- fas_close_video(fas_context);
- return private_show_error ("failed to allocate gray8 frame buffer", FAS_OUT_OF_MEMORY);
- }
-
- fas_context->rgb_buffer = 0;
- fas_context->gray8_buffer = 0;
- fas_context->rgb_already_converted = FAS_FALSE;
- fas_context->gray8_already_converted = FAS_FALSE;
-
- *context_ptr = fas_context;
-
-
- if (FAS_SUCCESS != fas_step_forward(*context_ptr))
- return private_show_error ("failure decoding first frame", FAS_NO_MORE_FRAMES);
-
- if (!fas_frame_available(*context_ptr))
- return private_show_error ("couldn't find a first frame (no valid frames in video stream)", FAS_NO_MORE_FRAMES);
-
-
-
- return FAS_SUCCESS;
-}
-
-/* fas_close_video */
-fas_error_type fas_close_video (fas_context_ref_type context)
-{
- if (NULL == context)
- return private_show_error ("NULL context provided for fas_close_video()", FAS_INVALID_ARGUMENT);
-
- if (!(context->is_video_active))
- {
- private_show_warning ("Redundant attempt to close an inactive video");
- return FAS_SUCCESS;
- }
-
- if (context->codec_context)
- if (avcodec_find_decoder (context->codec_context->codec_id))
- avcodec_close(context->codec_context);
-
- if (context->format_context)
- avformat_close_input (&context->format_context);
-
- if (context->rgb_frame_buffer)
- av_free (context->rgb_frame_buffer);
-
- if (context->gray8_frame_buffer)
- av_free (context->gray8_frame_buffer);
-
- if (context->rgb_buffer)
- av_free(context->rgb_buffer);
-
- if (context->gray8_buffer)
- av_free(context->gray8_buffer);
-
- if (context->frame_buffer)
- av_free (context->frame_buffer);
-
- seek_release_table (&(context->seek_table));
-
- context->is_video_active = FAS_FALSE;
-
- free (context);
-
- return FAS_SUCCESS;
-}
-
-
-/* fas_step_forward */
-fas_error_type fas_step_forward (fas_context_ref_type context)
-{
- if ((NULL == context) || (FAS_TRUE != context->is_video_active)) {
- return private_show_error ("invalid or unopened context", FAS_INVALID_ARGUMENT);
- }
-
- if (!context->is_frame_available)
- {
- private_show_warning ("tried to advance after end of frames");
- return FAS_SUCCESS;
- }
-
- context->current_frame_index++;
-
- AVPacket packet;
- while (FAS_TRUE)
- {
- if (av_read_frame(context->format_context, &packet) < 0)
- {
- /* finished */
- context->is_frame_available = FAS_FALSE;
- context->seek_table.completed = seek_true;
- return FAS_SUCCESS;
- }
-
- int frameFinished;
- if (packet.stream_index == context->stream_idx)
- {
- context->previous_dts = context->current_dts;
- context->current_dts = packet.dts;
-
- /* seek support: set first_dts */
- if (context->first_dts == AV_NOPTS_VALUE)
- context->first_dts = packet.dts;
-
- /* seek support: set key-packet info to previous packet's dts, when possible */
- /* note this -1 approach to setting the packet is a workaround for a common failure. setting
- to 0 would work just incur a huge penalty in videos that needed -1. Might be worth testing.
- */
- if (packet.flags & AV_PKT_FLAG_KEY)
- {
- //fprintf(stderr, "Packet: (F:%d %lld %lld)\n", context->current_frame_index, packet.pts, packet.dts);
-
- if (context->previous_dts == AV_NOPTS_VALUE)
- context->keyframe_packet_dts = packet.dts;
- else
- context->keyframe_packet_dts = context->previous_dts;
- }
-
- avcodec_decode_video2(context->codec_context, context->frame_buffer, &frameFinished, &packet);
-
- if (frameFinished)
- {
- /* seek support: (try to) add entry to seek_table */
- if (context->frame_buffer->key_frame)
- {
- // fprintf(stderr, "Frame : (PXX F%d: %lld %lld)\n", context->current_frame_index, packet.pts, packet.dts);
-
- seek_entry_type entry;
- entry.display_index = context->current_frame_index;
- entry.first_packet_dts = context->keyframe_packet_dts;
- entry.last_packet_dts = packet.dts;
-
- if (fas_get_frame_index(context) == FIRST_FRAME_INDEX)
- entry.first_packet_dts = context->first_dts;
-
- seek_append_table_entry(&context->seek_table, entry);
- }
-
- if (context->current_frame_index - FIRST_FRAME_INDEX + 1 > context->seek_table.num_frames)
- context->seek_table.num_frames = context->current_frame_index - FIRST_FRAME_INDEX + 1;
-
- break;
- }
- }
-
- av_free_packet(&packet);
- }
-
- context->rgb_already_converted = FAS_FALSE;
- context->gray8_already_converted = FAS_FALSE;
- av_free_packet(&packet);
- return FAS_SUCCESS;
-}
-
-/* fas_get_frame_index */
-
-int fas_get_frame_index (fas_context_ref_type context)
-{
- if (NULL == context)
- return private_show_error ("NULL context provided for fas_get_frame_index()", FAS_INVALID_ARGUMENT);
-
- if (FAS_TRUE != context->is_video_active)
- return private_show_error ("No video is open for fas_get_frame_index()", FAS_INVALID_ARGUMENT);
-
- return context->current_frame_index;
-}
-
-
-/* fas_get_frame */
-
-fas_error_type fas_get_frame (fas_context_ref_type context, fas_raw_image_type *image_ptr)
-{
- int buffer_size;
- fas_error_type fas_error;
-
- if (NULL == context || FAS_FALSE == context->is_video_active)
- return private_show_error ("null context or inactive video", FAS_INVALID_ARGUMENT);
-
- if (NULL == image_ptr)
- return private_show_error ("null image_ptr on get_frame", FAS_INVALID_ARGUMENT);
-
- if (!fas_frame_available(context))
- return private_show_error ("no frame available for extraction", FAS_NO_MORE_FRAMES);
-
- memset (image_ptr, 0, sizeof (fas_raw_image_type));
-
- switch (fmt)
- {
- case PIX_FMT_RGB24:
- image_ptr->bytes_per_line = context->codec_context->width * 3;
- image_ptr->color_space = FAS_RGB24;
- break;
- case PIX_FMT_BGR24:
- image_ptr->bytes_per_line = context->codec_context->width * 3;
- image_ptr->color_space = FAS_BGR24;
- break;
- case PIX_FMT_ARGB:
- image_ptr->bytes_per_line = context->codec_context->width * 4;
- image_ptr->color_space = FAS_ARGB32;
- break;
- case PIX_FMT_ABGR:
- image_ptr->bytes_per_line = context->codec_context->width * 4;
- image_ptr->color_space = FAS_ABGR32;
- break;
- case PIX_FMT_YUV420P:
- image_ptr->bytes_per_line = (context->codec_context->width * 3) >> 1;
- image_ptr->color_space = FAS_YUV420P;
- break;
- case PIX_FMT_YUYV422:
- image_ptr->bytes_per_line = context->codec_context->width * 2;
- image_ptr->color_space = FAS_YUYV422;
- break;
- case PIX_FMT_UYVY422:
- image_ptr->bytes_per_line = context->codec_context->width * 2;
- image_ptr->color_space = FAS_UYVY422;
- break;
- case PIX_FMT_YUV422P:
- image_ptr->bytes_per_line = context->codec_context->width * 2;
- image_ptr->color_space = FAS_YUV422P;
- break;
- case PIX_FMT_YUV444P:
- image_ptr->bytes_per_line = context->codec_context->width * 3;
- image_ptr->color_space = FAS_YUV444P;
- break;
- default: //iinserted TJR - to suppress warnings
- break;
- }
-
- buffer_size = image_ptr->bytes_per_line * context->codec_context->height;
-
- image_ptr->data = (unsigned char *)malloc (buffer_size);
- if (NULL == image_ptr->data)
- return private_show_error ("unable to allocate space for RGB image", FAS_OUT_OF_MEMORY);
-
- image_ptr->width = context->codec_context->width;
- image_ptr->height = context->codec_context->height;
-
-
- fas_error = private_convert_to_rgb(context);
-
- int j;
- unsigned char *from;
- unsigned char *to;
- for (j=0;j<context->codec_context->height; j++)
- {
- from = context->rgb_frame_buffer->data[0] + j*context->rgb_frame_buffer->linesize[0];
- to = image_ptr->data + j*image_ptr->bytes_per_line;
-
- memcpy(to, from, image_ptr->bytes_per_line);
- }
-
- if (FAS_SUCCESS != fas_error)
- return private_show_error ("unable to convert image to RGB", FAS_FAILURE);
-
- return FAS_SUCCESS;
-}
-
-/* fas_free_frame */
-
-void fas_free_frame (fas_raw_image_type image)
-{
- if (NULL == image.data)
- return;
-
- free (image.data);
-
- return;
-}
-
-/* fas_get_seek_table */
-seek_table_type fas_get_seek_table (fas_context_ref_type context)
-{
- seek_table_type null_table;
-
- null_table.array = NULL;
- null_table.completed = seek_false;
- null_table.num_frames = -1;
- null_table.num_entries = 0;
- null_table.allocated_size = 0;
-
- if (NULL == context || FAS_FALSE == context->is_video_active)
- return null_table;
-
- return context->seek_table;
-}
-
-/* fas_put_seek_table */
-fas_error_type fas_put_seek_table (fas_context_ref_type context, seek_table_type table)
-{
- if (NULL == context || FAS_FALSE == context->is_video_active)
- return private_show_error ("null context or inactive video", FAS_INVALID_ARGUMENT);
-
- seek_release_table (&context->seek_table);
- context->seek_table = seek_copy_table(table);
-
- return FAS_SUCCESS;
-}
-
-/* private_complete_seek_table */
-fas_error_type private_complete_seek_table (fas_context_ref_type context)
-{
- if ((NULL == context) || (FAS_FALSE == context->is_video_active))
- return private_show_error ("invalid or unopened context", FAS_INVALID_ARGUMENT);
-
- if (context->seek_table.completed)
- return FAS_SUCCESS;
-
- fas_error_type fas_error = fas_seek_to_nearest_key (context, context->seek_table.num_frames + FIRST_FRAME_INDEX - 1);
- if (FAS_SUCCESS != fas_error)
- return private_show_error("failed when trying to complete seek table (1) (first frame not labeled keyframe?)", fas_error);
-
- while (fas_frame_available(context))
- {
- // printf("%d\n", context->seek_table.num_frames);
- fas_step_forward(context);
- }
-
- if (!context->seek_table.completed)
- return private_show_error("failed when trying to complete seek table (2)", FAS_SEEK_ERROR);
-
- return FAS_SUCCESS;
-}
-
-/* fas_seek_to_frame */
-fas_error_type fas_seek_to_frame (fas_context_ref_type context, int target_index)
-{
-
- fas_error_type fas_error;
-
- if ((NULL == context) || (FAS_FALSE == context->is_video_active))
- return private_show_error ("invalid or unopened context", FAS_INVALID_ARGUMENT);
-
- // printf("seeking to %d (from %d)!\n", target_index, context->current_frame_index);
- if (target_index == context->current_frame_index)
- return FAS_SUCCESS;
-
- fas_error = fas_seek_to_nearest_key (context, target_index);
-
- if (fas_error != FAS_SUCCESS)
- return private_show_error ("error advancing to key frame before seek", fas_error);
-
- if (fas_get_frame_index(context) > target_index)
- return private_show_error ("error advancing to key frame before seek (index isn't right)", fas_error);
-
- while (fas_get_frame_index(context) < target_index)
- {
- if (fas_frame_available(context))
- fas_step_forward(context);
- else
- return private_show_error ("error advancing to request frame (probably out of range)", FAS_SEEK_ERROR);
- }
-
-
- return FAS_SUCCESS;
-}
-
-/* fas_seek_to_nearest_key */
-
-fas_error_type fas_seek_to_nearest_key (fas_context_ref_type context, int target_index)
-{
- return private_seek_to_nearest_key(context, target_index,0);
-}
-
-/* private_seek_to_nearest_key */
-
-fas_error_type private_seek_to_nearest_key (fas_context_ref_type context, int target_index, int offset)
-{
- if ((NULL == context) || (FAS_TRUE != context->is_video_active))
- return private_show_error ("invalid or unopened context", FAS_INVALID_ARGUMENT);
-
- // printf("HERE: from: %d to: %d offset: %d\n", context->current_frame_index, target_index, offset);
- fas_error_type fas_error;
- seek_entry_type seek_entry;
- seek_error_type seek_error = seek_get_nearest_entry (&(context->seek_table), &seek_entry, target_index, offset);
-
- if (seek_error != seek_no_error)
- return private_show_error ("error while searching seek table", FAS_SEEK_ERROR);
-
- if (seek_entry.display_index == context->current_frame_index)
- return FAS_SUCCESS;
-
- // printf("HERE: from: %d to: %d (%d) offset: %d\n", context->current_frame_index, target_index, seek_entry.display_index, offset);
- // printf("trying to seek to %d (%lld->%lld)\n", seek_entry.display_index, seek_entry.first_packet_dts, seek_entry.last_packet_dts);
-
- // if something goes terribly wrong, return bad current_frame_index
- context->current_frame_index = -2;
- context->is_frame_available = FAS_TRUE;
-
- int flags = 0;
- if (seek_entry.first_packet_dts <= context->current_dts)
- flags = AVSEEK_FLAG_BACKWARD;
-
- // printf("av_seek_frame: %lld\n", seek_entry.first_packet_dts);
- if (av_seek_frame(context->format_context, context->stream_idx, seek_entry.first_packet_dts, flags) < 0)
- return private_show_error("seek to keyframe failed", FAS_SEEK_ERROR);
-
-
- avcodec_flush_buffers (context->codec_context);
-
- fas_error = fas_step_forward (context);
-
- if (fas_error != FAS_SUCCESS || !context->is_frame_available)
- {
- // something bad has happened, try previous keyframe
- private_show_warning("processing of seeked keyframe failed, trying previous keyframe");
- return private_seek_to_nearest_key(context, target_index, offset + 1);
- }
-
- while (context->current_dts < seek_entry.last_packet_dts)
- {
- //printf("frame-times: current: %lld target: %lld is_key: %d\n", context->current_dts, seek_entry.last_packet_dts, context->frame_buffer->key_frame);
- fas_error = fas_step_forward(context);
- if (fas_error != FAS_SUCCESS)
- return private_show_error ("unable to process up to target frame (fas_seek_to_frame)", fas_error);
- }
-
- // printf("keyframe vitals: %d looking_for: %lld at: %lld\n", seek_entry.display_index, seek_entry.last_packet_dts, context->current_dts);
- if (context->current_dts != seek_entry.last_packet_dts)
- {
- /* seek to last key-frame, but look for this one */
- private_show_warning("missed keyframe, trying previous keyframe");
- return private_seek_to_nearest_key(context, target_index, offset + 1);
- }
-
- /* Ideally, we could just check if the frame decoded is of the correct time stamp... but... we need several ugly workarounds:
-
- 1) Some videos have bad keyframes that don't get decoded properly. In this cases, we need to go back a keyframe.
-
- 2) Other times, none of the frames are labeled keyframes. In these cases, we need to allow seeking to frame 0
- even when it's not labeled as a keyframe. Messy set of conditions.
- */
-
- if ((!context->frame_buffer->key_frame) && (seek_entry.display_index != 0))
- {
- private_show_warning("found keyframe, but not labeled as keyframe, so trying previous keyframe.");
- /* seek & look for previous keyframe */
- /* REMOVE FROM TABLE? */
- return private_seek_to_nearest_key(context, seek_entry.display_index - 1, 0);
- }
-
- context->current_frame_index = seek_entry.display_index;
-
- return FAS_SUCCESS;
-}
-
-/* fas_get_frame_count */
-
-int fas_get_frame_count_fast (fas_context_ref_type context)
-{
-
- if (NULL == context || FAS_FALSE == context->is_video_active)
- {
- private_show_error ("NULL or invalid context", FAS_INVALID_ARGUMENT);
- return -1;
- }
-
- if (context->seek_table.completed == seek_true)
- return context->seek_table.num_frames;
-
- return -1;
-}
-
-int fas_get_frame_count (fas_context_ref_type context)
-{
- int fast = fas_get_frame_count_fast(context);
- if (fast >= 0)
- return fast;
-
- int current_frame = fas_get_frame_index(context);
-
- fas_error_type fas_error;
-
- fas_error = private_complete_seek_table(context);
- if (FAS_SUCCESS != fas_error)
- {
- private_show_error("failed in get_frame_count trying to complete the seek table", fas_error);
- return -1;
- }
-
- // seek_show_raw_table(stderr, context->seek_table);
-
- fas_error = fas_seek_to_frame(context, current_frame);
- if (FAS_SUCCESS != fas_error)
- {
- private_show_error("failed in get_frame_count when trying to seek back to original location", fas_error);
- return -1;
- }
-
- fast = fas_get_frame_count_fast(context);
- if (fast < 0)
- private_show_warning("get_frame_count failed");
-
- return fast;
-}
-
-/* fas_frame_available */
-
-fas_boolean_type fas_frame_available (fas_context_ref_type context)
-{
- if (NULL == context)
- {
- private_show_error ("NULL context provided for fas_get_frame_index()", FAS_INVALID_ARGUMENT);
- return FAS_FALSE;
- }
-
- if (!context->is_video_active)
- return FAS_FALSE;
-
- return context->is_frame_available;
-}
-
-
-/* private_show_error */
-
-fas_error_type private_show_error (const char *message, fas_error_type error)
-{
- if (SHOW_ERROR_MESSAGES)
- fprintf (stderr, " ===> ffmpeg_fas: %s\n", message);
- return error;
-}
-
-void private_show_warning (const char *message)
-{
- if (SHOW_WARNING_MESSAGES)
- fprintf (stderr, " ---- ffmpeg_fas: %s\n", message);
- return;
-}
-
-
-/* private_convert_to_rgb */
-
-fas_error_type private_convert_to_rgb (fas_context_ref_type ctx)
-{
- if (ctx->rgb_already_converted)
- return FAS_SUCCESS;
-
-
- if (ctx->rgb_buffer == 0)
- {
- int numBytes = avpicture_get_size(fmt, ctx->codec_context->width,
- ctx->codec_context->height);
- ctx->rgb_buffer = (uint8_t *) av_malloc(numBytes*sizeof(uint8_t));
- avpicture_fill((AVPicture *) ctx->rgb_frame_buffer, ctx->rgb_buffer, fmt,
- ctx->codec_context->width, ctx->codec_context->height);
- }
- //
-/*
- if (!sws_ctx) {
- sws_ctx = sws_getContext(c->width, c->height, AV_PIX_FMT_YUV420P,
- c->width, c->height, c->pix_fmt,
- sws_flags, NULL, NULL, NULL);
- if (!sws_ctx) {
- //fprintf(stderr,
- // "Could not initialize the conversion context\n");
- exit(1);
- }
- }
-*/
-
-//int img_convert ( AVPicture * dst,
-//int dst_pix_fmt,
-//const AVPicture * src,
-//int src_pix_fmt,
-//int src_width,
-//int src_height
-//)
-
- //maybe tricky to convert: use sws_
- sws_scale(Sctx, // sws context
- ctx->frame_buffer->data, // src slice
- ctx->frame_buffer->linesize, // src stride
- 0, // src slice origin y
- ctx->frame_buffer->height, // src slice height
- ctx->rgb_frame_buffer->data, // dst
- ctx->rgb_frame_buffer->linesize ); // dst stride
- //instead of
- //if (img_convert((AVPicture *) ctx->rgb_frame_buffer, fmt, (AVPicture *) ctx->frame_buffer,
- // ctx->codec_context->pix_fmt,
- // ctx->codec_context->width, ctx->codec_context->height) < 0)
- // private_show_error("error converting to rgb", FAS_DECODING_ERROR);
-
- ctx->rgb_already_converted = FAS_TRUE;
-
- return FAS_SUCCESS;
-}
-
-
-/* private_convert_to_gray8 */
-/*
-fas_error_type private_convert_to_gray8 (fas_context_ref_type ctx)
-{
- if (ctx->gray8_already_converted)
- return FAS_SUCCESS;
-
- if (ctx->gray8_buffer == 0)
- {
- int numBytes = avpicture_get_size(PIX_FMT_GRAY8, ctx->codec_context->width,
- ctx->codec_context->height);
- ctx->gray8_buffer = (uint8_t *) av_malloc(numBytes*sizeof(uint8_t));
- avpicture_fill((AVPicture *) ctx->gray8_frame_buffer, ctx->gray8_buffer, PIX_FMT_GRAY8,
- ctx->codec_context->width, ctx->codec_context->height);
- }
-
- if (img_convert((AVPicture *) ctx->gray8_frame_buffer, PIX_FMT_GRAY8, (AVPicture *) ctx->frame_buffer,
- ctx->codec_context->pix_fmt,
- ctx->codec_context->width, ctx->codec_context->height) < 0)
- private_show_error("error converting to gray8", FAS_DECODING_ERROR);
-
- ctx->gray8_already_converted = FAS_TRUE;
-
- return FAS_SUCCESS;
-}
-*/
-
-int fas_get_current_width(fas_context_ref_type context)
-{
- return context->codec_context->width;
-}
-
-int fas_get_current_height(fas_context_ref_type context)
-{
- return context->codec_context->height;
-}
-
-unsigned long long fas_get_frame_duration(fas_context_ref_type context)
-{
- if (context->format_context->streams[context->stream_idx]->time_base.den != context->format_context->streams[context->stream_idx]->r_frame_rate.num
- || context->format_context->streams[context->stream_idx]->time_base.num != context->format_context->streams[context->stream_idx]->r_frame_rate.den)
- {
- double frac = (double)(context->format_context->streams[context->stream_idx]->r_frame_rate.den) / (double)(context->format_context->streams[context->stream_idx]->r_frame_rate.num);
- return (unsigned long long)(frac*10000000.);
- }
- else
- {
- return (unsigned long long)(((double)(context->format_context->streams[context->stream_idx]->time_base.num))
- /((double)(context->format_context->streams[context->stream_idx]->time_base.den))*10000000.);
- }
-}
-
-fas_error_type fas_fill_gray8_ptr(fas_context_ref_type context, unsigned char *y)
-{
- /* this conversion also seems to screw up sometimes -- pal8 -> gray8? legodragon.avi */
- //if (private_convert_to_gray8(context) != FAS_SUCCESS) TJR commented out
- // return FAS_FAILURE;
-
- int width = context->codec_context->width;
- int height = context->codec_context->height;
- int i;
- for (i=0;i < height; i++)
- memcpy(y + width * i, context->gray8_frame_buffer->data[0] + context->gray8_frame_buffer->linesize[0] * i, width);
-
- return FAS_SUCCESS;
-}
-
-fas_error_type fas_fill_420p_ptrs (fas_context_ref_type context, unsigned char *y, unsigned char *u, unsigned char *v)
-{
- AVFrame *p = context->frame_buffer;
-
- /* 411p to 420p conversion fails!? ... so i left this -ldb */
- if (context->codec_context->pix_fmt != PIX_FMT_YUV420P)
- return FAS_FAILURE;
-
- int width = context->codec_context->width;
- int height = context->codec_context->height;
- int i;
- for (i=0;i < height / 2; i++)
- {
- memcpy(y + width * (2*i) , p->data[0] + p->linesize[0] * (2*i) , width);
- memcpy(y + width * (2*i + 1), p->data[0] + p->linesize[0] * (2*i + 1), width);
- memcpy(u + width / 2 * i, p->data[1] + p->linesize[1] * i, width / 2);
- memcpy(v + width / 2 * i, p->data[2] + p->linesize[2] * i, width / 2);
- }
-
- return FAS_SUCCESS;
-}
-
diff --git a/rotord/src/ffmpeg_fas.h b/rotord/src/ffmpeg_fas.h
deleted file mode 100644
index 0c51103..0000000
--- a/rotord/src/ffmpeg_fas.h
+++ /dev/null
@@ -1,130 +0,0 @@
-/*****************************************************************************
- * 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 <http://www.gnu.org/licenses/>.
- *
- ******************************************************************************/
-
-#ifndef FFMPEG_FAS_H
-#define FFMPEG_FAS_H
-
-/* If C++ then we need to __extern "C". Compiler defines __cplusplus */
-#ifdef __cplusplus
-#define __extern extern "C"
-#else
-#define __extern extern
-#endif
-
-
-#ifndef UINT64_C
-#define UINT64_C(c) (c ## ULL)
-#endif
-
-#include "seek_indices.h"
-#include <libswscale/swscale.h>
-
-
-static struct SwsContext *Sctx;
-static int sws_flags = SWS_BICUBIC;
-
-
-typedef enum
-{
- FAS_GRAY8 = 1,
- FAS_RGB24 = 2,
- FAS_BGR24 = 3,
- FAS_ARGB32 = 4,
- FAS_ABGR32 = 5,
- FAS_YUV420P = 6,
- FAS_YUYV422 = 7,
- FAS_UYVY422 = 8,
- FAS_YUV422P = 9,
- FAS_YUV444P = 10,
-} fas_color_space_type;
-
-typedef struct
-{
- unsigned char *data;
- int width;
- int height;
- int bytes_per_line;
- fas_color_space_type color_space;
-} fas_raw_image_type;
-
-
-/**********************************************************************
- * Video IO Types
- **********************************************************************/
-
-typedef struct fas_context_struct* fas_context_ref_type;
-
-typedef enum
-{
- FAS_SUCCESS,
- FAS_FAILURE,
- FAS_INVALID_ARGUMENT,
- FAS_OUT_OF_MEMORY,
- FAS_UNSUPPORTED_FORMAT,
- FAS_UNSUPPORTED_CODEC,
- FAS_NO_MORE_FRAMES,
- FAS_DECODING_ERROR,
- FAS_SEEK_ERROR,
-} fas_error_type;
-
-typedef enum
-{
- FAS_FALSE = 0,
- FAS_TRUE = 1
-} fas_boolean_type;
-
-
-__extern void fas_initialize (fas_boolean_type logging, fas_color_space_type format);
-__extern void fas_set_format (fas_color_space_type format);
-
-__extern fas_error_type fas_open_video (fas_context_ref_type *context_ptr, char *file_path);
-__extern fas_error_type fas_close_video (fas_context_ref_type context);
-
-__extern char* fas_error_message (fas_error_type error);
-
-__extern fas_boolean_type fas_frame_available (fas_context_ref_type context);
-__extern int fas_get_frame_index (fas_context_ref_type context);
-__extern fas_error_type fas_step_forward (fas_context_ref_type context);
-
-__extern fas_error_type fas_get_frame (fas_context_ref_type context, fas_raw_image_type *image_ptr);
-__extern void fas_free_frame (fas_raw_image_type image);
-
-__extern fas_error_type fas_seek_to_nearest_key (fas_context_ref_type context, int target_index);
-__extern fas_error_type fas_seek_to_frame (fas_context_ref_type context, int target_index);
-
-__extern int fas_get_frame_count (fas_context_ref_type context);
-__extern int fas_get_frame_count_fast (fas_context_ref_type context);
-
-__extern fas_error_type fas_put_seek_table (fas_context_ref_type context, seek_table_type table);
-__extern seek_table_type fas_get_seek_table (fas_context_ref_type context);
-
-/* will extract raw 420p if the video is in that format -- needs to be alloced ahead of time*/
-__extern fas_error_type fas_fill_420p_ptrs (fas_context_ref_type context, unsigned char *y, unsigned char *u, unsigned char *v);
-
-/* will extract gray8 data from movie (will convert to ensure you get it) -- need to be alloc'ed ahead of time*/
-__extern fas_error_type fas_fill_gray8_ptr(fas_context_ref_type context, unsigned char *y);
-
-__extern int fas_get_current_width(fas_context_ref_type context);
-__extern int fas_get_current_height(fas_context_ref_type context);
-
-__extern unsigned long long fas_get_frame_duration(fas_context_ref_type context);
-
-#endif
diff --git a/rotord/src/graph.cpp b/rotord/src/graph.cpp
index 2e89a4c..5487717 100644
--- a/rotord/src/graph.cpp
+++ b/rotord/src/graph.cpp
@@ -279,6 +279,7 @@ bool Graph::parseJson(string &data,string &media_path){
}
//we know the json validates so clear the existing graph
clear();
+ Node_factory factory;
check_audio(root["audio"].asString(),media_path);
init(root["ID"].asString(),root["description"].asString());
Json::Value jnodes = root["nodeDefinitions"];
@@ -394,6 +395,7 @@ bool Graph::parseJson(string &data,string &media_path){
}
bool Graph::parseXml(string media_path){
clear();
+ Node_factory factory;
check_audio(xml.getAttribute("patchbay","audio","",0),media_path);
init(xml.getAttribute("patchbay","ID","",0),xml.getValue("patchbay","",0));
if(xml.pushTag("patchbay")) {
diff --git a/rotord/src/graph.h b/rotord/src/graph.h
index d614b3b..b2132b9 100644
--- a/rotord/src/graph.h
+++ b/rotord/src/graph.h
@@ -61,7 +61,6 @@ namespace Rotor {
bool cancelled;
float progress;
private:
- Node_factory factory;
int outW,outH;
};
diff --git a/rotord/src/libavwrapper.cpp b/rotord/src/libavwrapper.cpp
index b7b5688..321725e 100644
--- a/rotord/src/libavwrapper.cpp
+++ b/rotord/src/libavwrapper.cpp
@@ -80,8 +80,9 @@ void libav::maybeInitFFMpegLib()
{
if (b_is_one_time_inited)
return;
- av_register_all();
- avcodec_register_all();
+ FFMS_Init(0, 0); //should do for all
+ //av_register_all();
+ //avcodec_register_all();
avformat_network_init();
b_is_one_time_inited = true;
}
@@ -556,7 +557,56 @@ bool libav::decoder::avtry(int result, const std::string& msg) {
return true;
}
+ void libav::ffms2_decoder::cleanup(){
+ if (loaded) {
+ mutex.lock();
+ FFMS_DestroyVideoSource(videosource);
+ mutex.unlock();
+ loaded=false;
+ }
+}
+bool libav::ffms2_decoder::open(const std::string& filename){
+ mutex.lock();
+ loaded=false;
+ FFMS_Index *index = FFMS_MakeIndex(filename.c_str(), 0, 0, NULL, NULL, FFMS_IEH_ABORT, NULL, NULL, &errinfo);
+ if (index == NULL) {
+ std::cerr<<"ffmpegsource: "<<errinfo.Buffer<<std::endl;
+ mutex.unlock();
+ return false;
+ }
+ int trackno = FFMS_GetFirstTrackOfType(index, FFMS_TYPE_VIDEO, &errinfo);
+ if (trackno < 0) {
+ std::cerr<<"ffmpegsource: "<<errinfo.Buffer<<std::endl;
+ mutex.unlock();
+ return false;
+ }
+ videosource = FFMS_CreateVideoSource(filename.c_str(), trackno, index, 1, FFMS_SEEK_NORMAL, &errinfo);
+ if (videosource == NULL) {
+ std::cerr<<"ffmpegsource: "<<errinfo.Buffer<<std::endl;
+ mutex.unlock();
+ return false;
+ }
+ FFMS_DestroyIndex(index);
+ videoprops = FFMS_GetVideoProperties(videosource);
+ const FFMS_Frame *propframe = FFMS_GetFrame(videosource, 0, &errinfo);
+ w=propframe->EncodedWidth;
+ h=propframe->EncodedHeight;
+ //propframe->EncodedPixelFormat;
+
+ if (FFMS_SetOutputFormatV2(videosource, pixfmts, propframe->EncodedWidth, propframe->EncodedHeight, FFMS_RESIZER_BICUBIC, &errinfo)) {
+ std::cerr<<"ffmpegsource: "<<errinfo.Buffer<<std::endl;
+ mutex.unlock();
+ return false;
+ }
+ int framenumber = 0; /* valid until next call to FFMS_GetFrame* on the same video object */
+
+
+ std::cerr<<"ffmpegsource: successfully opened "<<filename<<std::endl;
+ loaded=true;
+ mutex.unlock();
+ return loaded;
+}
///////////////////////////
// encoder methods //
@@ -1245,7 +1295,7 @@ void libav::exporter::open_video(AVFormatContext *oc, AVCodec *codec, AVStream *
AVFrame *frame = avcodec_alloc_frame();
int got_packet, ret;
- av_init_packet(&pkt);
+ //av_init_packet(&pkt); 111013 NOT NECESSARY
c = st->codec;
//get_audio_frame(samples, audio_input_frame_size, c->channels);
@@ -1406,7 +1456,7 @@ void libav::exporter::open_video(AVFormatContext *oc, AVCodec *codec, AVStream *
if (oc->oformat->flags & AVFMT_RAWPICTURE) {
// Raw video case - directly store the picture in the packet //
AVPacket pkt;
- av_init_packet(&pkt);
+ //av_init_packet(&pkt); ///removed 101013 NOT NECESSARY
pkt.flags |= AV_PKT_FLAG_KEY;
pkt.stream_index = st->index;
@@ -1418,7 +1468,7 @@ void libav::exporter::open_video(AVFormatContext *oc, AVCodec *codec, AVStream *
} else {
AVPacket pkt = { 0 };
int got_packet;
- av_init_packet(&pkt);
+ //av_init_packet(&pkt); ///removed 101013 NOT NECESSARY
// encode the image //
diff --git a/rotord/src/libavwrapper.h b/rotord/src/libavwrapper.h
index d30ea95..870815f 100644
--- a/rotord/src/libavwrapper.h
+++ b/rotord/src/libavwrapper.h
@@ -69,6 +69,8 @@ extern "C" {
#include <math.h>
#include <vector>
+#include <ffms.h>
+
namespace libav {
@@ -154,6 +156,68 @@ namespace libav {
};
+ class ffms2_decoder
+ {
+ public:
+ ffms2_decoder(){
+ maybeInitFFMpegLib();
+ pixfmts[0] = FFMS_GetPixFmt("rgb24");
+ pixfmts[1] = -1;
+ h=0;
+ w=0;
+ videosource=NULL;
+ loaded=false;
+ errinfo.Buffer = errmsg;
+ errinfo.BufferSize = sizeof(errmsg);
+ errinfo.ErrorType = FFMS_ERROR_SUCCESS;
+ errinfo.SubType = FFMS_ERROR_SUCCESS;
+ }
+ ~ffms2_decoder(){
+ cleanup();
+ }
+ void cleanup();
+ bool open(const std::string& filename);
+ float getFrameRate(){
+ if (loaded) return (((float)videoprops->FPSNumerator)/((float)videoprops->FPSDenominator));
+ else return -1.0f;
+ }
+ int getNumberOfFrames(){
+ if (loaded) return videoprops->NumFrames;
+ else return -1;
+ }
+ int getNumberOfChannels(){
+ return 3; //this is what we convert to
+ }
+ int getWidth(){
+ return w;
+ }
+ int getHeight(){
+ return h;
+ }
+ bool fetchFrame(int width,int height,int wanted){
+ if (FFMS_SetOutputFormatV2(videosource, pixfmts, width, height, FFMS_RESIZER_BICUBIC, &errinfo)) {
+ std::cerr<<"ffmpegsource: "<<errinfo.Buffer<<std::endl;
+ return false;
+ }
+ frame = FFMS_GetFrame(videosource, wanted%videoprops->NumFrames, &errinfo);
+ if (frame == NULL) {
+ std::cerr<<"ffmpegsource: "<<errinfo.Buffer<<std::endl;
+ return false;
+ }
+ return true;
+
+ }
+
+ FFMS_VideoSource *videosource;
+ FFMS_VideoProperties *videoprops;
+ FFMS_Frame *frame;
+ FFMS_ErrorInfo errinfo;
+ char errmsg[1024];
+ int pixfmts[2];
+ bool loaded;
+ int h,w;
+ };
+
/*
// TODO - finish refactoring based on
// http://svn.gnumonks.org/trunk/21c3-video/ffmpeg/ffmpeg-0.4.9-pre1/output_example.c
diff --git a/rotord/src/ofUtils.o b/rotord/src/ofUtils.o
new file mode 100644
index 0000000..d31a12b
--- /dev/null
+++ b/rotord/src/ofUtils.o
Binary files differ
diff --git a/rotord/src/private_errors.h b/rotord/src/private_errors.h
deleted file mode 100644
index 9369ae3..0000000
--- a/rotord/src/private_errors.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*****************************************************************************
- * 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 <http://www.gnu.org/licenses/>.
- *
- ******************************************************************************/
-
-#ifndef FAS_PRIVATE_ERROR_H
-#define FAS_PRIVATE_ERROR_H
-
-#if defined( _WIN32 ) && defined( STATIC_DLL )
-static int SHOW_ERROR_MESSAGES;
-static int SHOW_WARNING_MESSAGES;
-#else
-int SHOW_ERROR_MESSAGES;
-int SHOW_WARNING_MESSAGES;
-#endif /* _WIN32 && STATIC_DLL */
-#endif
diff --git a/rotord/src/rendercontext.h b/rotord/src/rendercontext.h
index f15ca31..b525a07 100644
--- a/rotord/src/rendercontext.h
+++ b/rotord/src/rendercontext.h
@@ -103,7 +103,6 @@ namespace Rotor {
Audio_thumbnailer *audio_thumb;
Graph graph;
- Node_factory factory;
float output_framerate;
};
diff --git a/rotord/src/rotor.cpp b/rotord/src/rotor.cpp
index ee18dbd..d26cdec 100644
--- a/rotord/src/rotor.cpp
+++ b/rotord/src/rotor.cpp
@@ -80,7 +80,7 @@ float Parameter::get(const Time_spec& time){ //gets input and updates variable
return value;
}
-bool Video_loader::load(const string &_filename){
+bool _Video_loader::load(const string &_filename){
Logger& logger = Logger::get("Rotor");
if (isLoaded) {
player.cleanup(); ///should be in decoder class?
@@ -102,7 +102,7 @@ bool Video_loader::load(const string &_filename){
return false;
}
-Image* Video_loader::output(const Frame_spec &frame){
+Image* _Video_loader::output(const Frame_spec &frame){
if (isLoaded){
//this approach is running into the inability to seek when requesting playback speed > 1.
diff --git a/rotord/src/rotor.h b/rotord/src/rotor.h
index eba5be1..ff8675a 100644
--- a/rotord/src/rotor.h
+++ b/rotord/src/rotor.h
@@ -29,7 +29,6 @@ Definitions of base classes and types for rotor rendering graph
#include "utils.h"
#include "cvimage.h"
#include "libavwrapper.h"
-#include "ffmpeg-fas_wrapper.h"
//using namespace cv;
namespace Rotor {
@@ -879,6 +878,33 @@ namespace Rotor {
};
#define VIDEOFRAMES_frame 1
#define VIDEOFRAMES_blend 2
+ class _Video_loader: public Image_node {
+ public:
+ _Video_loader(){
+ create_parameter("speed","number","video playback speed","Speed",1.0f,0.0f,0.0f);
+ create_parameter("framerate","number","framerate override","Frame rate",0.0f,0.0f,0.0f);
+ create_attribute("filename","name of video file to load","File name","");
+ create_attribute("mode","frame mode","Mode","frame",{"frame","blend"});
+ title="Video loader";
+ description="Loads a video file";
+ };
+ _Video_loader(map<string,string> &settings): _Video_loader() {
+ base_settings(settings);
+ isLoaded=false;
+ if (attributes["filename"]->value!="") {
+ load(find_setting(settings,"media_path","")+attributes["filename"]->value);
+ }
+ lastframe=0;
+ };
+ ~_Video_loader(){};
+ bool load(const string &filename);
+ Image *output(const Frame_spec &frame);
+ _Video_loader* clone(map<string,string> &_settings) { return new _Video_loader(_settings);};
+ bool isLoaded;
+ private:
+ libav::decoder player;
+ int lastframe;
+ };
class Video_loader: public Image_node {
public:
Video_loader(){
@@ -898,12 +924,49 @@ namespace Rotor {
lastframe=0;
};
~Video_loader(){};
- bool load(const string &filename);
- Image *output(const Frame_spec &frame);
+ bool load(const string &filename){
+ Poco::Logger& logger = Poco::Logger::get("Rotor");
+ if (isLoaded) {
+ player.cleanup(); ///should be in decoder class?
+ isLoaded=false;
+ }
+ isLoaded=player.open(filename);
+ if (isLoaded){
+ logger.information("Video_loader loaded "+filename+": "\
+ +toString(player.getNumberOfFrames())+" frames, "\
+ +toString(player.getFrameRate())+" fps, "\
+ +toString(player.getWidth())+"x"+toString(player.getHeight())\
+ +", channels:"+toString(player.getNumberOfChannels()));
+ return true;
+ }
+ logger.error("Video_loader failed to load "+filename);
+ return false;
+ }
+ Image *output(const Frame_spec &frame){
+ if (isLoaded){
+ float clipframerate=(parameters["framerate"]->value==0.0f?player.getFrameRate():parameters["framerate"]->value);
+ float clipspeed=(clipframerate/frame.framerate)*parameters["speed"]->value;
+ int wanted=(((int) ((frame.time*frame.framerate)+0.5))%max(1,player.getNumberOfFrames()-1));
+ if (wanted!=lastframe){
+ if (!player.fetchFrame(frame.w,frame.h,wanted)) { //seek fail
+ Poco::Logger& logger = Poco::Logger::get("Rotor");
+ logger.error("Video_loader failed to seek frame "+toString(wanted)+" of "+attributes["filename"]->value);
+
+ if (image.w>0) return &image; //just return the previous frame if possible
+ else return nullptr;
+ }
+ image.setup_fromRGB(frame.w,frame.h,player.frame->Data[0],player.frame->Linesize[0]-(frame.w*3));
+ lastframe=wanted;
+ }
+ return &image;
+ }
+ return nullptr;
+ };
Video_loader* clone(map<string,string> &_settings) { return new Video_loader(_settings);};
bool isLoaded;
private:
- libav::decoder player;
+ //ffmpegsource::decoder player;
+ libav::ffms2_decoder player;
int lastframe;
};
class Video_output: public Image_node {
diff --git a/rotord/src/seek_indices.c b/rotord/src/seek_indices.c
deleted file mode 100644
index cb877c3..0000000
--- a/rotord/src/seek_indices.c
+++ /dev/null
@@ -1,319 +0,0 @@
-/*****************************************************************************
- * 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 <http://www.gnu.org/licenses/>.
- *
- ******************************************************************************/
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <stdint.h>
-#include <string.h>
-
-#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;i<t1.num_entries;i++)
- {
- // printf("(%d %d) (%lld %lld) (%lld %lld)\n",
- // t1.array[i].display_index, t2.array[i].display_index,
- // t1.array[i].decode_time, t2.array[i].decode_time,
- // t1.array[i].display_time, t2.array[i].display_time);
- if ((t1.array[i].display_index != t2.array[i].display_index) ||
- (t1.array[i].last_packet_dts != t2.array[i].last_packet_dts) ||
- (t1.array[i].first_packet_dts != t2.array[i].first_packet_dts))
- return 0;
- }
-
- return 1;
-}
-
-seek_table_type seek_init_table (int initial_size)
-{
- seek_table_type table;
-
- if (initial_size < 0)
- initial_size = DEFAULT_INITIAL_SIZE;
-
- table.num_entries = 0;
- table.num_frames = -1;
- table.completed = seek_false;
-
- table.array = (seek_entry_type *)malloc (initial_size * sizeof(seek_entry_type));
-
- if (NULL == table.array)
- table.allocated_size = 0;
- else
- table.allocated_size = initial_size;
-
- return table;
-}
-
-/*
- * seek_release_table
- */
-
-void seek_release_table (seek_table_type *table)
-{
- table->num_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;i<source.num_entries;i++)
- dest.array[i] = source.array[i];
-
- return dest;
-}
-
-seek_error_type seek_append_table_entry (seek_table_type *table, seek_entry_type entry)
-{
-
- if (NULL == table || NULL == table->array)
- 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 (i<offset) /* target was lower than first element (including offset) */
- return private_show_error ("target index out of table range (too small)", seek_bad_argument);
-
- *entry = table->array[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;i<ans.num_entries;i++)
- fscanf(table_file, "%d %lld %lld\n", &(ans.array[i].display_index), &(ans.array[i].first_packet_dts), &(ans.array[i].last_packet_dts));
-
- fclose(table_file);
- return ans;
-}
-
-seek_error_type seek_show_raw_table (FILE* file, 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(file, "%d %d %d\n", table.num_frames, table.num_entries, completed_flag);
- for (index = 0; index < table.num_entries; index++)
- {
- entry = &(table.array[index]);
-
- fprintf (file, "%d %lld %lld\n", entry->display_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;
-}
diff --git a/rotord/src/seek_indices.h b/rotord/src/seek_indices.h
deleted file mode 100644
index e908979..0000000
--- a/rotord/src/seek_indices.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/*****************************************************************************
- * 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 <http://www.gnu.org/licenses/>.
- *
- ******************************************************************************/
-
-#ifndef FAS_SEEK_INDICES_H
-#define FAS_SEEK_INDICES_H
-
-#include <stdint.h>
-#include <stdio.h>
-
-/* If C++ then we need to __extern "C". Compiler defines __cplusplus */
-#ifdef __cplusplus
-#define __extern extern "C"
-#else
-#define __extern extern
-#endif
-
-
-/**********************************************************************
- * Seek Table Types
- **********************************************************************/
-
-typedef enum
-{
- seek_no_error,
- seek_unknown_error,
- seek_bad_argument,
- seek_malloc_failed,
-} seek_error_type;
-
-typedef enum
-{
- seek_false = 0,
- seek_true = 1
-} seek_boolean_type;
-
-typedef struct
-{
- int display_index;
- int64_t first_packet_dts;
- int64_t last_packet_dts;
-} seek_entry_type;
-
-typedef struct
-{
- seek_entry_type *array;
- seek_boolean_type completed;
- int num_frames; // total number of frames
- int num_entries; // ie, number of seek-points (keyframes)
- int allocated_size;
-} seek_table_type;
-
-
-
-/**********************************************************************
- * Seek Table Functions
- **********************************************************************/
-
-
-__extern seek_table_type seek_init_table (int initial_size);
-__extern void seek_release_table (seek_table_type *table);
-
-__extern seek_table_type seek_copy_table (seek_table_type source);
-__extern int compare_seek_tables(seek_table_type t1, seek_table_type t2);
-
-__extern seek_error_type seek_append_table_entry (seek_table_type *table, seek_entry_type entry);
-
-__extern seek_error_type seek_get_nearest_entry (seek_table_type *table, seek_entry_type *entry, int display_index, int offset);
-
-__extern seek_error_type seek_show_table (seek_table_type table); /* human readable */
-__extern seek_error_type seek_show_raw_table (FILE *file, seek_table_type table);
-
-__extern seek_table_type read_table_file(char *name); /* read raw file */
-
-#endif
-
-/**** End of File *****************************************************/