diff options
Diffstat (limited to 'ffmpeg-fas/test')
| -rwxr-xr-x | ffmpeg-fas/test/build.sh | 7 | ||||
| -rw-r--r-- | ffmpeg-fas/test/dump_frames.c | 67 | ||||
| -rw-r--r-- | ffmpeg-fas/test/dump_keyframes.c | 76 | ||||
| -rw-r--r-- | ffmpeg-fas/test/external_seek_test.c | 172 | ||||
| -rw-r--r-- | ffmpeg-fas/test/generate_seek_table.c | 209 | ||||
| -rw-r--r-- | ffmpeg-fas/test/movie_info.c | 81 | ||||
| -rwxr-xr-x | ffmpeg-fas/test/run_test.py | 56 | ||||
| -rw-r--r-- | ffmpeg-fas/test/seek_test.c | 162 | ||||
| -rw-r--r-- | ffmpeg-fas/test/show_seek_table.c | 59 | ||||
| -rw-r--r-- | ffmpeg-fas/test/test_support.h | 67 |
10 files changed, 956 insertions, 0 deletions
diff --git a/ffmpeg-fas/test/build.sh b/ffmpeg-fas/test/build.sh new file mode 100755 index 0000000..d00dd63 --- /dev/null +++ b/ffmpeg-fas/test/build.sh @@ -0,0 +1,7 @@ +LINK="../lib/libffmpeg_fas.so -lm -lz " +gcc dump_frames.c -I.. $LINK -o dump_frames +gcc dump_keyframes.c -I.. $LINK -o dump_keyframes +gcc show_seek_table.c -I.. $LINK -o show_seek_table +gcc seek_test.c -I.. $LINK -o seek_test +gcc external_seek_test.c -I.. $LINK -o external_seek_test +gcc generate_seek_table.c -I.. -I../ffmpeg/ ../ffmpeg/libavformat/libavformat.a ../ffmpeg/libavutil/libavutil.a ../ffmpeg/libavcodec/libavcodec.a -lm -lz ../lib/libffmpeg_fas.so -o generate_seek_table
\ No newline at end of file diff --git a/ffmpeg-fas/test/dump_frames.c b/ffmpeg-fas/test/dump_frames.c new file mode 100644 index 0000000..6b4ccb7 --- /dev/null +++ b/ffmpeg-fas/test/dump_frames.c @@ -0,0 +1,67 @@ +/***************************************************************************** + * 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" +#include "test_support.h" +#include <stdio.h> + +int main (int argc, char **argv) +{ + char filename_buffer [255]; + + fas_error_type video_error; + fas_context_ref_type context; + fas_raw_image_type image_buffer; + + if (argc < 2) { + fprintf (stderr, "usage: %s <video_file>\n", argv[0]); + return -1; + } + + fas_initialize (FAS_FALSE); + + fprintf(stderr, "%s : ",argv[1]); + video_error = fas_open_video (&context, argv[1]); + if (video_error != FAS_SUCCESS) + fail("failed to open\n"); + + int counter = 0; + while (fas_frame_available (context)) + { + + if (FAS_SUCCESS != fas_get_frame (context, &image_buffer)) + fail("failed on rgb image\n"); + + char filename[50]; + sprintf(filename, "frame_%04d.ppm", counter); + + fprintf(stderr, "Writing %s (counter=%d frame_index=%d)\n", filename, counter, fas_get_frame_index(context)); + ppm_save(&image_buffer, filename); + + fas_free_frame (image_buffer); + + video_error = fas_step_forward (context); + counter++; + } + + success(); + +} diff --git a/ffmpeg-fas/test/dump_keyframes.c b/ffmpeg-fas/test/dump_keyframes.c new file mode 100644 index 0000000..4e1333e --- /dev/null +++ b/ffmpeg-fas/test/dump_keyframes.c @@ -0,0 +1,76 @@ +/***************************************************************************** + * 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" +#include "seek_indices.h" +#include "test_support.h" +#include <stdio.h> + +int main (int argc, char **argv) +{ + fas_error_type video_error; + fas_context_ref_type context, seek_context; + + if (argc < 3) { + fprintf (stderr, "usage: %s <video_file> <seek_table>\n", argv[0]); + fail("arguments\n"); + } + + seek_table_type table = read_table_file(argv[2]); + if (table.num_entries == 0) + fail("bad table\n"); + + fas_initialize (FAS_TRUE); + + video_error = fas_open_video (&context, argv[1]); + if (video_error != FAS_SUCCESS) fail("fail on open\n"); + + video_error = fas_put_seek_table(context, table); + if (video_error != FAS_SUCCESS) fail("fail on put_seek_table\n"); + + video_error = fas_open_video (&seek_context, argv[1]); + if (video_error != FAS_SUCCESS) fail("fail on open\n"); + + int i; + for(i=0;i<table.num_entries;i++) + { + // int frame_index = table.array[table.num_entries - i - 1].display_index; + int frame_index = table.array[i].display_index; + if (FAS_SUCCESS != fas_seek_to_frame(context, frame_index)) + fail("failed on seek"); + + fas_raw_image_type image_buffer; + + if (FAS_SUCCESS != fas_get_frame (context, &image_buffer)) + fail("failed on rgb image\n"); + + char filename[50]; + sprintf(filename, "frame_%04d.ppm", frame_index); + + fprintf(stderr, "Writing %s (seek_table_value=%d frame_index=%d)\n", filename, frame_index, fas_get_frame_index(context)); + ppm_save(&image_buffer, filename); + + fas_free_frame (image_buffer); + } + + success(); +} + diff --git a/ffmpeg-fas/test/external_seek_test.c b/ffmpeg-fas/test/external_seek_test.c new file mode 100644 index 0000000..d81c141 --- /dev/null +++ b/ffmpeg-fas/test/external_seek_test.c @@ -0,0 +1,172 @@ +/***************************************************************************** + * 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/>. + * + ******************************************************************************/ + +/* test seek using external table */ + +#include "ffmpeg_fas.h" +#include "seek_indices.h" +#include "test_support.h" +#include <stdio.h> + +#define TEST_SET_SIZE 1000 +#define N_ITERATIONS 500 + +int compare_frames(fas_raw_image_type img1, fas_raw_image_type img2) +{ + // printf("(%d %d) (%d %d) (%d %d) (%d %d)\n", img1.width, img2.width, + // img1.height, img2.height, + // img1.bytes_per_line, img2.bytes_per_line, + // img1.color_space, img2.color_space); + + if ((img1.width != img2.width) || + (img1.height != img2.height) || + (img1.bytes_per_line != img2.bytes_per_line) || + (img1.color_space != img2.color_space)) + return 0; + + int i,j; + int mask = 0; + + for (i=0;i<img1.height;i++) + for(j=0;j<img1.bytes_per_line;j++) + { + //printf("%d ", (img1.data[i*img1.bytes_per_line+j] - img2.data[i*img1.bytes_per_line+j+j])); + mask |= (img1.data[i*img1.bytes_per_line+j] - img2.data[i*img1.bytes_per_line+j]); + } + + if (mask == 0) + return 1; + else + return 0; +} + +void do_random_test(fas_context_ref_type context, int start, int stop, int count) +{ + // printf ("start: %d stop: %d\n", start, stop ); + + while (fas_get_frame_index(context) < start) + if (FAS_SUCCESS != fas_step_forward(context)) + fail("failed on advancement\n"); + + fas_raw_image_type *ref_frames = malloc( (stop - start + 1)* sizeof(fas_raw_image_type)); + + int i; + fas_error_type video_error; + + while (fas_get_frame_index(context) <= stop) + { + i = fas_get_frame_index(context) - start; + + video_error = fas_get_frame(context, &(ref_frames[i])); + if (video_error != FAS_SUCCESS) fail("fail on test(1)\n"); + + video_error = fas_step_forward(context); + if (video_error != FAS_SUCCESS) fail("fail on test(2)\n"); + + } + + int index = -1; + int prev_index; + + for (i=0;i<count;i++) + { + int offset = random() % (stop - start + 1); + prev_index = index; + index = start + offset; + + video_error = fas_seek_to_frame(context, index); + if (video_error != FAS_SUCCESS) fail("fail on test(seek)\n"); + + + fas_raw_image_type test_frame; + video_error = fas_get_frame(context, &test_frame); + if (video_error != FAS_SUCCESS) fail("fail on test(seek2)\n"); + + // printf("offset: %d / %d\n", offset, stop - start + 1); + + if (!compare_frames(test_frame, ref_frames[offset])) + { + char buffer[70]; + + sprintf(buffer, "fail-%d-test.ppm", index); + ppm_save(&test_frame, buffer); + sprintf(buffer, "fail-%d-ref.ppm", index); + ppm_save(&ref_frames[offset], buffer); + sprintf(buffer, "failed on compare after seeking (%d->%d)\n", prev_index, index); + + fail(buffer); + } + + fas_free_frame(test_frame); + } + + for (i=0;i<stop - start + 1;i++) + free(ref_frames[i].data); + + free(ref_frames); +} + +int main (int argc, char **argv) +{ + fas_error_type video_error; + fas_context_ref_type context; + + if (argc < 3) { + fprintf (stderr, "usage: %s <video_file> <seek_table>\n", argv[0]); + fail("arguments\n"); + } + + fprintf(stderr, "%s : ", argv[1]); + + seek_table_type table = read_table_file(argv[2]); + if (table.num_entries == 0) + fail("bad table\n"); + + fas_initialize (FAS_FALSE); + + video_error = fas_open_video (&context, argv[1]); + if (video_error != FAS_SUCCESS) fail("fail on open\n"); + + video_error = fas_put_seek_table(context, table); + if (video_error != FAS_SUCCESS) fail("fail on put_seek_table\n"); + + if (fas_get_frame_count(context) < 0) + fail("n_frames = -1\n"); + + if (fas_get_frame_count(context) < TEST_SET_SIZE) + do_random_test(context, 0, fas_get_frame_count(context) - 1, N_ITERATIONS); + else if (fas_get_frame_count(context) < TEST_SET_SIZE * 2) + { + do_random_test(context, 0, fas_get_frame_count(context) / 2 - 1, N_ITERATIONS / 2); + do_random_test(context, fas_get_frame_count(context) / 2 + 1, fas_get_frame_count(context) - 1 , N_ITERATIONS / 2); + } + else + { + do_random_test(context, 0, TEST_SET_SIZE, N_ITERATIONS / 2); + do_random_test(context, fas_get_frame_count(context) - TEST_SET_SIZE, fas_get_frame_count(context) - 1 , N_ITERATIONS / 2); + } + + seek_release_table(&table); + fas_close_video(context); + + success(); +} + diff --git a/ffmpeg-fas/test/generate_seek_table.c b/ffmpeg-fas/test/generate_seek_table.c new file mode 100644 index 0000000..5549f57 --- /dev/null +++ b/ffmpeg-fas/test/generate_seek_table.c @@ -0,0 +1,209 @@ +/***************************************************************************** + * 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 "libavcodec/avcodec.h" +#include "libavformat/avformat.h" +#include <stdio.h> +#include <string.h> +#include "seek_indices.h" + +/* This executable is used for creating experimental seek tables. + The show_seek_table executable will show the seek-table as ffmpeg_fas + currently creates them. + */ + +int main (int argc, char **argv) +{ + av_log_level = AV_LOG_QUIET; + + if (argc < 2) { + fprintf (stderr, "usage: %s <video_file>\n", argv[0]); + return -1; + } + + av_register_all(); + + AVFormatContext *pFormatCtx; + if (av_open_input_file(&pFormatCtx, argv[1], NULL, 0, NULL) !=0) + return -1; + + if (av_find_stream_info(pFormatCtx)<0) + return -1; + + unsigned int stream_id = -1; + unsigned int i; + + for (i = 0; i < pFormatCtx->nb_streams; i++) + if (pFormatCtx->streams[i]->codec->codec_type == CODEC_TYPE_VIDEO) + { + stream_id = i; + break; + } + + if (stream_id == -1) + return -1; + + AVCodecContext *pCodecCtx = pFormatCtx->streams[stream_id]->codec; + AVCodec *pCodec; + pCodec = avcodec_find_decoder(pCodecCtx->codec_id); + if (pCodec==NULL) + return -1; + + if (avcodec_open(pCodecCtx, pCodec)<0) + return -1; + + + // printf("\n%s \n",argv[1]); + + AVPacket Packet; + int count = 0; + int key_packets = 0; + int non_key_packets = 0; + + int frame_count = 0; + int key_frames = 0; + int non_key_frames = 0; + + AVFrame *pFrame; + pFrame=avcodec_alloc_frame(); + int frameFinished; + + seek_table_type table; + table = seek_init_table (16); + seek_entry_type entry; + + int64_t key_packet_dts; + int64_t prev_packet_dts = AV_NOPTS_VALUE; + int64_t first_packet_dts; /* ensure first keyframe gets first packet */ + + int is_first_packet = 1; + int frames_have_label = 1; + + // const char *format_name = pFormatCtx->iformat->name; + // const char *codec_name = pFormatCtx->streams[stream_id]->codec->codec->name; + + + /* these avi formats do not have labeled keyframes (the packets are labeled only and the packets and keyframe align 1-to-1 */ + /* DISABLING THIS TYPE OF GENERATION (these videos will be unseekable) */ + // fprintf(stderr, "format: (%s) codec: (%s)\n", format_name, codec_name); +/* + * if (!strcmp(format_name, "avi")) + * if (!strcmp(codec_name, "aasc") || + * !strcmp(codec_name, "camtasia") || + * !strcmp(codec_name, "cinepak") || + * !strcmp(codec_name, "cyuv") || + * !strcmp(codec_name, "huffyuv") || + * !strcmp(codec_name, "indeo2") || + * !strcmp(codec_name, "indeo3") || + * !strcmp(codec_name, "msrle") || + * !strcmp(codec_name, "msvideo1") || + * !strcmp(codec_name, "mszh") || + * !strcmp(codec_name, "qpeg") || + * !strcmp(codec_name, "truemotion1") || + * !strcmp(codec_name, "ultimotion") || + * !strcmp(codec_name, "vp3") || + * !strcmp(codec_name, "zlib")) + * frames_have_label = 0; + */ + + while (av_read_frame(pFormatCtx, &Packet) >= 0) + { + if (Packet.stream_index == stream_id) + { + // fprintf(stderr, "Packet: (P%d: %lld %lld %d)\n", count, Packet.pts, Packet.dts, Packet.flags); + if ((Packet.flags & PKT_FLAG_KEY) || is_first_packet ) + { + /* when keyframes overlap in the stream, that means multiple packets labeled 'keyframe' will arrive before + the keyframe itself. this results in wrong assignments all around, but only the first one needs to be right. + for all the rest, the seek-code will rewind to the previous keyframe to get them right. + */ + if (is_first_packet) + { + first_packet_dts = Packet.dts; + is_first_packet = 0; + } + + // fprintf(stderr, "Packet: (P%d: %lld %lld)\n", count, Packet.pts, Packet.dts); + + /* first keyframe gets own dts, others get previous packet's dts.. this is workaround for some mpegs */ + /* sometimes you need the previous packet from the supposed keyframe packet to get a frame back that is */ + /* actually a keyframe */ + + if (prev_packet_dts == AV_NOPTS_VALUE) + key_packet_dts = Packet.dts; + else + key_packet_dts = prev_packet_dts; + + if (Packet.flags & PKT_FLAG_KEY) + key_packets++; + else + non_key_packets++; + } + else + non_key_packets++; + + + avcodec_decode_video(pCodecCtx, pFrame, &frameFinished, Packet.data, Packet.size); + + if (frameFinished) + { + + // fprintf(stderr, "Frame : (P%d F%d: %lld %lld L:%d)\n", count, frame_count, Packet.pts, Packet.dts, pFrame->key_frame); + if ((pFrame->key_frame && frames_have_label) || ((Packet.flags & PKT_FLAG_KEY) && !frames_have_label)) + { + key_frames++; + + entry.display_index = frame_count; + entry.first_packet_dts = key_packet_dts; + entry.last_packet_dts = Packet.dts; + + /* ensure first keyframe gets first packet dts */ + if (frame_count == 0) + entry.first_packet_dts = first_packet_dts; + + seek_append_table_entry(&table, entry); + + // fprintf(stderr, "Frame : (P%d F%d: %lld %lld)\n", count, frame_count, Packet.pts, Packet.dts); + } + else + non_key_frames++; + frame_count++; + } + + count++; + prev_packet_dts = Packet.dts; + } + + av_free_packet(&Packet); + } + + // printf("\n"); + + fprintf (stderr, "Packets: key: %d nonkey: %d total: %d\n", key_packets, non_key_packets, count); + fprintf (stderr, "Frames : key: %d nonkey: %d total: %d\n", key_frames, non_key_frames, frame_count); + + table.completed = seek_true; + table.num_frames = frame_count; + + seek_show_raw_table(stdout, table); + + return 1; +} diff --git a/ffmpeg-fas/test/movie_info.c b/ffmpeg-fas/test/movie_info.c new file mode 100644 index 0000000..f7bf40e --- /dev/null +++ b/ffmpeg-fas/test/movie_info.c @@ -0,0 +1,81 @@ +/***************************************************************************** + * 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 <libavcodec/avcodec.h> +#include <libavformat/avformat.h> + +#include <stdio.h> + +int main(int argc, char *argv[]) { + AVFormatContext *pFormatCtx; + int i, videoStream; + AVCodecContext *pCodecCtx; + AVCodec *pCodec; + AVFrame *pFrame; + AVFrame *pFrameRGB; + AVPacket packet; + int frameFinished; + int numBytes; + uint8_t *buffer; + + if(argc < 2) { + printf("Please provide a movie file\n"); + return -1; + } + // Register all formats and codecs + av_register_all(); + + // Open video file + if(av_open_input_file(&pFormatCtx, argv[1], NULL, 0, NULL)!=0) + return -1; // Couldn't open file + + // Retrieve stream information + if(av_find_stream_info(pFormatCtx)<0) + return -1; // Couldn't find stream information + + // Dump information about file onto standard error + dump_format(pFormatCtx, 0, argv[1], 0); + + // Find the first video stream + videoStream=-1; + for(i=0; i<pFormatCtx->nb_streams; i++) + if(pFormatCtx->streams[i]->codec->codec_type==CODEC_TYPE_VIDEO) { + videoStream=i; + break; + } + if(videoStream==-1) + return -1; // Didn't find a video stream + + // Get a pointer to the codec context for the video stream + pCodecCtx=pFormatCtx->streams[videoStream]->codec; + + // Find the decoder for the video stream + pCodec=avcodec_find_decoder(pCodecCtx->codec_id); + if(pCodec==NULL) { + fprintf(stderr, "Unsupported codec!\n"); + return -1; // Codec not found + } + // Open codec + if(avcodec_open(pCodecCtx, pCodec)<0) + return -1; // Could not open codec + + return 0; +} diff --git a/ffmpeg-fas/test/run_test.py b/ffmpeg-fas/test/run_test.py new file mode 100755 index 0000000..38dbb21 --- /dev/null +++ b/ffmpeg-fas/test/run_test.py @@ -0,0 +1,56 @@ +#!/usr/bin/python + +import sys +import os + +def readFilelist(filename): + try: + f = open(filename, 'r') + except: + return [] + return [ele[:-1] for ele in f.readlines()] + +def create_filter_func(cmd, log_file): + if log_file == "": + return lambda filename : 0 == os.system(cmd + " " + filename) + else: + return lambda filename : 0 == os.system(cmd + " " + filename + " 2>> " + log_file) + +def write_filelist(files, filename): + f = open(filename, 'w') + for arg in files: + f.write(arg + '\n') + f.close() + +if __name__ == "__main__": + if len(sys.argv) < 3 or len(sys.argv) > 4: + print "Usage: " + sys.argv[0] + " <test_executable> <file_list>" + raise SystemExit + + + if not os.path.isfile(sys.argv[1]): + print sys.argv[1] + " not found" + raise SystemExit + + cmd = sys.argv[1] + base_name = cmd.split('/')[-1] + + success_file = base_name + ".pass" + fail_file = base_name + ".fail" + + if len(sys.argv) == 4: + log_file = sys.argv[3] + if os.path.isfile(log_file): + os.system("rm " + log_file) + else: + log_file = "" + + files = readFilelist(sys.argv[2]) + + filterfunc = create_filter_func(cmd, log_file) + successful = filter(filterfunc, files) + failed = list(set(files) - set(successful)) + + write_filelist(failed, fail_file) + write_filelist(successful, success_file) + diff --git a/ffmpeg-fas/test/seek_test.c b/ffmpeg-fas/test/seek_test.c new file mode 100644 index 0000000..77f045e --- /dev/null +++ b/ffmpeg-fas/test/seek_test.c @@ -0,0 +1,162 @@ +/***************************************************************************** + * 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" +#include "seek_indices.h" +#include "test_support.h" +#include <stdio.h> + +#define TEST_SET_SIZE 1000 +#define N_ITERATIONS 500 + +int compare_frames(fas_raw_image_type img1, fas_raw_image_type img2) +{ + // printf("(%d %d) (%d %d) (%d %d) (%d %d)\n", img1.width, img2.width, + // img1.height, img2.height, + // img1.bytes_per_line, img2.bytes_per_line, + // img1.color_space, img2.color_space); + + if ((img1.width != img2.width) || + (img1.height != img2.height) || + (img1.bytes_per_line != img2.bytes_per_line) || + (img1.color_space != img2.color_space)) + return 0; + + int i,j; + int mask = 0; + + for (i=0;i<img1.height;i++) + for(j=0;j<img1.bytes_per_line;j++) + { + //printf("%d ", (img1.data[i*img1.bytes_per_line+j] - img2.data[i*img1.bytes_per_line+j+j])); + mask |= (img1.data[i*img1.bytes_per_line+j] - img2.data[i*img1.bytes_per_line+j]); + } + + if (mask == 0) + return 1; + else + return 0; +} + +void do_random_test(fas_context_ref_type context, int start, int stop, int count) +{ + // printf ("start: %d stop: %d\n", start, stop ); + + while (fas_get_frame_index(context) < start) + if (FAS_SUCCESS != fas_step_forward(context)) + fail("failed on advancement\n"); + + fas_raw_image_type *ref_frames = malloc( (stop - start + 1)* sizeof(fas_raw_image_type)); + + int i; + fas_error_type video_error; + + while (fas_get_frame_index(context) <= stop) + { + i = fas_get_frame_index(context) - start; + + video_error = fas_get_frame(context, &(ref_frames[i])); + if (video_error != FAS_SUCCESS) fail("fail on test(1)\n"); + + video_error = fas_step_forward(context); + if (video_error != FAS_SUCCESS) fail("fail on test(2)\n"); + + } + + int index = -1; + int prev_index; + + for (i=0;i<count;i++) + { + int offset = random() % (stop - start + 1); + prev_index = index; + index = start + offset; + + video_error = fas_seek_to_frame(context, index); + if (video_error != FAS_SUCCESS) fail("fail on test(seek)\n"); + + + fas_raw_image_type test_frame; + video_error = fas_get_frame(context, &test_frame); + if (video_error != FAS_SUCCESS) fail("fail on test(seek2)\n"); + + // printf("offset: %d / %d\n", offset, stop - start + 1); + + if (!compare_frames(test_frame, ref_frames[offset])) + { + char buffer[70]; + + sprintf(buffer, "fail-%d-test.ppm", index); + ppm_save(&test_frame, buffer); + sprintf(buffer, "fail-%d-ref.ppm", index); + ppm_save(&ref_frames[offset], buffer); + sprintf(buffer, "failed on compare after seeking (%d->%d)\n", prev_index, index); + + fail(buffer); + } + + fas_free_frame(test_frame); + } + + for (i=0;i<stop - start + 1;i++) + free(ref_frames[i].data); + + free(ref_frames); +} + +int main (int argc, char **argv) +{ + fas_error_type video_error; + fas_context_ref_type context; + + if (argc < 2) { + fprintf (stderr, "usage: %s <video_file>\n", argv[0]); + fail("arguments\n"); + } + + fprintf(stderr, "%s : ", argv[1]); + + fas_initialize (FAS_FALSE); + + video_error = fas_open_video (&context, argv[1]); + if (video_error != FAS_SUCCESS) fail("fail on open\n"); + + if (fas_get_frame_count(context) < 0) + fail("failed on counting frames (completing seek table... bad table?)\n"); + + if (fas_get_frame_count(context) < TEST_SET_SIZE) + do_random_test(context, 0, fas_get_frame_count(context) - 1, N_ITERATIONS); + else if (fas_get_frame_count(context) < TEST_SET_SIZE * 2) + { + do_random_test(context, 0, fas_get_frame_count(context) / 2 - 1, N_ITERATIONS / 2); + do_random_test(context, fas_get_frame_count(context) / 2 + 1, fas_get_frame_count(context) - 1 , N_ITERATIONS / 2); + } + else + { + do_random_test(context, 0, TEST_SET_SIZE, N_ITERATIONS / 2); + do_random_test(context, fas_get_frame_count(context) - TEST_SET_SIZE, fas_get_frame_count(context) - 1 , N_ITERATIONS / 2); + } + + fas_close_video(context); + + success(); +} + diff --git a/ffmpeg-fas/test/show_seek_table.c b/ffmpeg-fas/test/show_seek_table.c new file mode 100644 index 0000000..6974bc2 --- /dev/null +++ b/ffmpeg-fas/test/show_seek_table.c @@ -0,0 +1,59 @@ +/***************************************************************************** + * 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 "seek_indices.h" +#include "ffmpeg_fas.h" +#include <stdio.h> + +int main (int argc, char **argv) +{ + fas_error_type video_error; + fas_context_ref_type context; + fas_raw_image_type image_buffer; + + if (argc < 2) { + fprintf (stderr, "usage: %s <video_file>\n", argv[0]); + return -1; + } + + fas_initialize (FAS_FALSE); + + video_error = fas_open_video (&context, argv[1]); + if (video_error != FAS_SUCCESS) + return -1; + + while (fas_frame_available (context)) + { + if (FAS_SUCCESS != fas_get_frame (context, &image_buffer)) + return -1; + fas_free_frame (image_buffer); + + video_error = fas_step_forward (context); + } + + seek_table_type table; + table = fas_get_seek_table(context); + + seek_show_raw_table(stdout, table); + + return 1; +} + diff --git a/ffmpeg-fas/test/test_support.h b/ffmpeg-fas/test/test_support.h new file mode 100644 index 0000000..5b91a1a --- /dev/null +++ b/ffmpeg-fas/test/test_support.h @@ -0,0 +1,67 @@ +/***************************************************************************** + * 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_TEST_SUPPORT +#define FAS_TEST_SUPPORT + +#include <stdio.h> +#include <stdlib.h> + +#define fail(x) { fprintf(stderr, "fail : "); fprintf(stderr, x); exit(EXIT_FAILURE); } +#define success() { fprintf(stderr, "success\n"); exit(EXIT_SUCCESS); } + +/* + * static void pgm_save(ppt_raw_image_type *image, char *filename) + * { + * FILE *f; + * int i; + * + * f=fopen(filename,"w"); + * fprintf(f,"P5\n%d\n%d\n%d\n", image->width, image->height, 255); + * + * for(i=0; i<image->height; i++) { + * fwrite(image->data + i * image->bytes_per_line, 1, image->width, f); + * } + * + * fclose(f); + * } + */ + +static void ppm_save(fas_raw_image_type *image, char *filename) +{ + FILE *f; + int i; + + if (image->color_space != FAS_RGB24) { + return; + } + + f=fopen(filename,"wb"); + fprintf(f,"P6\n%d %d\n%d\n", image->width, image->height, 255); + + for(i=0; i<image->height; i++) { + fwrite(image->data + i * image->bytes_per_line, 1, image->width * 3, f); + } + + fclose(f); +} + +#endif |
