rmovie 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/ext/rmovie/Makefile +149 -0
- data/ext/rmovie/config.h +3 -0
- data/ext/rmovie/extconf.rb +43 -0
- data/ext/rmovie/mkmf.log +24 -0
- data/ext/rmovie/pre-setup.rb +4 -0
- data/ext/rmovie/quadrupel/Makefile +32 -0
- data/ext/rmovie/quadrupel/TODO +15 -0
- data/ext/rmovie/quadrupel/mkinstalldirs +100 -0
- data/ext/rmovie/quadrupel/qp_frame.c +266 -0
- data/ext/rmovie/quadrupel/qp_frame.h +49 -0
- data/ext/rmovie/quadrupel/qp_movie.c +1179 -0
- data/ext/rmovie/quadrupel/qp_movie.h +81 -0
- data/ext/rmovie/quadrupel/qp_util.c +27 -0
- data/ext/rmovie/quadrupel/qp_util.h +18 -0
- data/ext/rmovie/quadrupel/test.c +60 -0
- data/ext/rmovie/rmovie_frame.c +236 -0
- data/ext/rmovie/rmovie_frame.h +10 -0
- data/ext/rmovie/rmovie_main.c +100 -0
- data/ext/rmovie/rmovie_movie.c +349 -0
- data/ext/rmovie/rmovie_movie.h +28 -0
- data/lib/rmovie/version.rb +45 -0
- data/test/export_movie.rb +7 -0
- data/test/get_frame.rb +10 -0
- data/test/get_frames_reverse.rb +11 -0
- data/test/init_rmovie.rb +7 -0
- data/test/media/1701-D.mov +0 -0
- data/test/media/Ballad of the Sneak.mp3 +0 -0
- data/test/media/irnbru-singsong.mov +0 -0
- data/test/media/test.mov +0 -0
- data/test/pixel_format.rb +10 -0
- data/test/test_rmovie.rb +93 -0
- data/test/to_s.rb +27 -0
- data/test/to_string.rb +19 -0
- metadata +83 -0
data/ext/rmovie/Makefile
ADDED
@@ -0,0 +1,149 @@
|
|
1
|
+
|
2
|
+
SHELL = /bin/sh
|
3
|
+
|
4
|
+
#### Start of system configuration section. ####
|
5
|
+
|
6
|
+
srcdir = .
|
7
|
+
topdir = /usr/lib/ruby/1.8/i686-linux
|
8
|
+
hdrdir = $(topdir)
|
9
|
+
VPATH = $(srcdir):$(topdir):$(hdrdir)
|
10
|
+
prefix = $(DESTDIR)/usr
|
11
|
+
exec_prefix = $(DESTDIR)/usr
|
12
|
+
sitedir = $(DESTDIR)/usr/lib/ruby/site_ruby
|
13
|
+
rubylibdir = $(libdir)/ruby/$(ruby_version)
|
14
|
+
docdir = $(datarootdir)/doc/$(PACKAGE)
|
15
|
+
dvidir = $(docdir)
|
16
|
+
datarootdir = $(prefix)/share
|
17
|
+
archdir = $(rubylibdir)/$(arch)
|
18
|
+
sbindir = $(exec_prefix)/sbin
|
19
|
+
psdir = $(docdir)
|
20
|
+
localedir = $(datarootdir)/locale
|
21
|
+
htmldir = $(docdir)
|
22
|
+
datadir = $(DESTDIR)/usr/share
|
23
|
+
includedir = $(prefix)/include
|
24
|
+
infodir = $(DESTDIR)/usr/share/info
|
25
|
+
sysconfdir = $(DESTDIR)/etc
|
26
|
+
mandir = $(DESTDIR)/usr/share/man
|
27
|
+
libdir = $(DESTDIR)/usr/lib
|
28
|
+
sharedstatedir = $(prefix)/com
|
29
|
+
oldincludedir = $(DESTDIR)/usr/include
|
30
|
+
pdfdir = $(docdir)
|
31
|
+
sitearchdir = $(sitelibdir)/$(sitearch)
|
32
|
+
bindir = $(exec_prefix)/bin
|
33
|
+
localstatedir = $(DESTDIR)/var/lib
|
34
|
+
sitelibdir = $(sitedir)/$(ruby_version)
|
35
|
+
libexecdir = $(exec_prefix)/libexec
|
36
|
+
|
37
|
+
CC = i686-pc-linux-gnu-gcc
|
38
|
+
LIBRUBY = $(LIBRUBY_SO)
|
39
|
+
LIBRUBY_A = lib$(RUBY_SO_NAME)-static.a
|
40
|
+
LIBRUBYARG_SHARED = -Wl,-R -Wl,$(libdir) -L$(libdir) -L. -l$(RUBY_SO_NAME)
|
41
|
+
LIBRUBYARG_STATIC = -l$(RUBY_SO_NAME)-static
|
42
|
+
|
43
|
+
RUBY_EXTCONF_H = config.h
|
44
|
+
CFLAGS = -fPIC -O2 -march=athlon-xp -fPIC
|
45
|
+
INCFLAGS = -I. -I. -I/usr/lib/ruby/1.8/i686-linux -I. -Iquadrupel
|
46
|
+
CPPFLAGS = -DRUBY_EXTCONF_H=\"$(RUBY_EXTCONF_H)\"
|
47
|
+
CXXFLAGS = $(CFLAGS)
|
48
|
+
DLDFLAGS = -Lquadrupel/
|
49
|
+
LDSHARED = $(CC) -shared
|
50
|
+
AR = i686-pc-linux-gnu-ar
|
51
|
+
EXEEXT =
|
52
|
+
|
53
|
+
RUBY_INSTALL_NAME = ruby18
|
54
|
+
RUBY_SO_NAME = ruby18
|
55
|
+
arch = i686-linux
|
56
|
+
sitearch = i686-linux
|
57
|
+
ruby_version = 1.8
|
58
|
+
ruby = /usr/bin/ruby18
|
59
|
+
RUBY = $(ruby)
|
60
|
+
RM = rm -f
|
61
|
+
MAKEDIRS = mkdir -p
|
62
|
+
INSTALL = /bin/install -c
|
63
|
+
INSTALL_PROG = $(INSTALL) -m 0755
|
64
|
+
INSTALL_DATA = $(INSTALL) -m 644
|
65
|
+
COPY = cp
|
66
|
+
|
67
|
+
#### End of system configuration section. ####
|
68
|
+
|
69
|
+
preload =
|
70
|
+
|
71
|
+
libpath = $(libdir)
|
72
|
+
LIBPATH = -L'$(libdir)' -Wl,-R'$(libdir)'
|
73
|
+
DEFFILE =
|
74
|
+
|
75
|
+
CLEANFILES =
|
76
|
+
DISTCLEANFILES =
|
77
|
+
|
78
|
+
extout =
|
79
|
+
extout_prefix =
|
80
|
+
target_prefix =
|
81
|
+
LOCAL_LIBS =
|
82
|
+
LIBS = $(LIBRUBYARG_SHARED) -lavformat -lavcodec -ldl -lcrypt -lm -lc -lquadrupel
|
83
|
+
SRCS = rmovie_frame.c rmovie_movie.c rmovie_main.c
|
84
|
+
OBJS = rmovie_frame.o rmovie_movie.o rmovie_main.o
|
85
|
+
TARGET = rmovie
|
86
|
+
DLLIB = $(TARGET).so
|
87
|
+
EXTSTATIC =
|
88
|
+
STATIC_LIB =
|
89
|
+
|
90
|
+
RUBYCOMMONDIR = $(sitedir)$(target_prefix)
|
91
|
+
RUBYLIBDIR = $(sitelibdir)$(target_prefix)
|
92
|
+
RUBYARCHDIR = $(sitearchdir)$(target_prefix)
|
93
|
+
|
94
|
+
TARGET_SO = $(DLLIB)
|
95
|
+
CLEANLIBS = $(TARGET).so $(TARGET).il? $(TARGET).tds $(TARGET).map
|
96
|
+
CLEANOBJS = *.o *.a *.s[ol] *.pdb *.exp *.bak
|
97
|
+
|
98
|
+
all: $(DLLIB)
|
99
|
+
static: $(STATIC_LIB)
|
100
|
+
|
101
|
+
clean:
|
102
|
+
@-$(RM) $(CLEANLIBS) $(CLEANOBJS) $(CLEANFILES)
|
103
|
+
|
104
|
+
distclean: clean
|
105
|
+
@-$(RM) Makefile $(RUBY_EXTCONF_H) conftest.* mkmf.log
|
106
|
+
@-$(RM) core ruby$(EXEEXT) *~ $(DISTCLEANFILES)
|
107
|
+
|
108
|
+
realclean: distclean
|
109
|
+
install: install-so install-rb
|
110
|
+
|
111
|
+
install-so: $(RUBYARCHDIR)
|
112
|
+
install-so: $(RUBYARCHDIR)/$(DLLIB)
|
113
|
+
$(RUBYARCHDIR)/$(DLLIB): $(DLLIB)
|
114
|
+
$(INSTALL_PROG) $(DLLIB) $(RUBYARCHDIR)
|
115
|
+
install-rb: pre-install-rb install-rb-default
|
116
|
+
install-rb-default: pre-install-rb-default
|
117
|
+
pre-install-rb: Makefile
|
118
|
+
pre-install-rb-default: Makefile
|
119
|
+
$(RUBYARCHDIR):
|
120
|
+
$(MAKEDIRS) $@
|
121
|
+
|
122
|
+
site-install: site-install-so site-install-rb
|
123
|
+
site-install-so: install-so
|
124
|
+
site-install-rb: install-rb
|
125
|
+
|
126
|
+
.SUFFIXES: .c .m .cc .cxx .cpp .C .o
|
127
|
+
|
128
|
+
.cc.o:
|
129
|
+
$(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $<
|
130
|
+
|
131
|
+
.cxx.o:
|
132
|
+
$(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $<
|
133
|
+
|
134
|
+
.cpp.o:
|
135
|
+
$(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $<
|
136
|
+
|
137
|
+
.C.o:
|
138
|
+
$(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $<
|
139
|
+
|
140
|
+
.c.o:
|
141
|
+
$(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) -c $<
|
142
|
+
|
143
|
+
$(DLLIB): $(OBJS)
|
144
|
+
@-$(RM) $@
|
145
|
+
$(LDSHARED) $(DLDFLAGS) $(LIBPATH) -o $@ $(OBJS) $(LOCAL_LIBS) $(LIBS)
|
146
|
+
|
147
|
+
|
148
|
+
|
149
|
+
$(OBJS): ruby.h defines.h $(RUBY_EXTCONF_H)
|
data/ext/rmovie/config.h
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'mkmf'
|
4
|
+
|
5
|
+
dir_config("ffmpeg")
|
6
|
+
#dir_config("quadrupel")
|
7
|
+
|
8
|
+
def fail(err)
|
9
|
+
printf(" extconf failed: %s\n", err)
|
10
|
+
exit 1
|
11
|
+
end
|
12
|
+
|
13
|
+
unless have_library('avcodec', 'avcodec_init')
|
14
|
+
fail('need avcodec library')
|
15
|
+
end
|
16
|
+
|
17
|
+
unless have_library('avformat', 'av_register_all')
|
18
|
+
fail('need avformat library')
|
19
|
+
end
|
20
|
+
|
21
|
+
#unless have_library('quadrupel', 'quadrupel_init')
|
22
|
+
# fail('need quadrupel library')
|
23
|
+
#end
|
24
|
+
|
25
|
+
#unless have_header("qp_util.h")
|
26
|
+
# fail("can't find quadrupel header files")
|
27
|
+
#end
|
28
|
+
|
29
|
+
if with_config("strict") or enable_config("strict")
|
30
|
+
$CFLAGS += " -Wall "
|
31
|
+
end
|
32
|
+
|
33
|
+
if with_config("debug") or enable_config("debug")
|
34
|
+
$CFLAGS += " -g"
|
35
|
+
end
|
36
|
+
|
37
|
+
# hard code quadrupel stuff for now
|
38
|
+
$INCFLAGS << ' ' + '-Iquadrupel'.chomp
|
39
|
+
$LDFLAGS << ' ' + '-Lquadrupel/'.chomp
|
40
|
+
$LIBS << ' ' + '-lquadrupel'.chomp
|
41
|
+
|
42
|
+
create_header "config.h"
|
43
|
+
create_makefile("rmovie")
|
data/ext/rmovie/mkmf.log
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
have_library: checking for avcodec_init() in -lavcodec... -------------------- yes
|
2
|
+
|
3
|
+
"i686-pc-linux-gnu-gcc -o conftest -I. -I/usr/lib/ruby/1.8/i686-linux -I. -O2 -march=athlon-xp -fPIC conftest.c -L'/usr/lib' -Wl,-R'/usr/lib' -lruby18-static -lavcodec -ldl -lcrypt -lm -lc"
|
4
|
+
checked program was:
|
5
|
+
/* begin */
|
6
|
+
1: /*top*/
|
7
|
+
2: int main() { return 0; }
|
8
|
+
3: int t() { avcodec_init(); return 0; }
|
9
|
+
/* end */
|
10
|
+
|
11
|
+
--------------------
|
12
|
+
|
13
|
+
have_library: checking for av_register_all() in -lavformat... -------------------- yes
|
14
|
+
|
15
|
+
"i686-pc-linux-gnu-gcc -o conftest -I. -I/usr/lib/ruby/1.8/i686-linux -I. -O2 -march=athlon-xp -fPIC conftest.c -L'/usr/lib' -Wl,-R'/usr/lib' -lavcodec -lruby18-static -lavformat -lavcodec -ldl -lcrypt -lm -lc"
|
16
|
+
checked program was:
|
17
|
+
/* begin */
|
18
|
+
1: /*top*/
|
19
|
+
2: int main() { return 0; }
|
20
|
+
3: int t() { av_register_all(); return 0; }
|
21
|
+
/* end */
|
22
|
+
|
23
|
+
--------------------
|
24
|
+
|
@@ -0,0 +1,32 @@
|
|
1
|
+
.SUFFIXES:
|
2
|
+
.SUFFIXES: .c .o
|
3
|
+
|
4
|
+
CC = gcc
|
5
|
+
CFLAGS = -g
|
6
|
+
ALL_CFLAGS = -fpic $(CFLAGS)
|
7
|
+
|
8
|
+
LIBNAME = libquadrupel.a
|
9
|
+
HEADERS = qp_movie.h qp_frame.h qp_util.h
|
10
|
+
OBJ = qp_movie.o qp_frame.o qp_util.o
|
11
|
+
ARFLAGS = -rcs
|
12
|
+
|
13
|
+
srcdir= ./
|
14
|
+
prefix = ./
|
15
|
+
libdir = $(prefix)/lib/
|
16
|
+
includedir = $(prefix)/include/
|
17
|
+
|
18
|
+
%.o : %.c $(HEADERS)
|
19
|
+
$(CC) -c $(ALL_CFLAGS) $(CPPFLAGS) $< -o $@
|
20
|
+
|
21
|
+
all: $(OBJ)
|
22
|
+
$(AR) $(ARFLAGS) $(LIBNAME) *.o
|
23
|
+
|
24
|
+
install: all installdirs
|
25
|
+
cp $(HEADERS) $(includedir)
|
26
|
+
cp $(LIBNAME) $(libdir)
|
27
|
+
|
28
|
+
installdirs:
|
29
|
+
$(srcdir)/mkinstalldirs $(libdir) $(includedir)
|
30
|
+
|
31
|
+
clean:
|
32
|
+
rm -f $(OBJ) $(LIBNAME)
|
@@ -0,0 +1,15 @@
|
|
1
|
+
TODO:
|
2
|
+
|
3
|
+
* Add flag to allow creation of frame based/time based movies
|
4
|
+
time based: allows seeking, not frame accurate.
|
5
|
+
frame based: no seek support, frame accurate, slower since it must
|
6
|
+
decode to move thru a movie.
|
7
|
+
|
8
|
+
* Implement seeking using blender's anim.c code as a starting point.
|
9
|
+
|
10
|
+
* Optimize av_get_frame to decode directly into a buffer managed by the
|
11
|
+
library using gstreamer's gst-ffmpeg decoder as a starting point.
|
12
|
+
|
13
|
+
* Implement audio in export
|
14
|
+
|
15
|
+
* Re-add support for raw video input (it was part of output_example.c but I removed it until I get basic exporting working)
|
@@ -0,0 +1,100 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
# mkinstalldirs --- make directory hierarchy
|
3
|
+
# Author: Noah Friedman <friedman@prep.ai.mit.edu>
|
4
|
+
# Created: 1993-05-16
|
5
|
+
# Public domain
|
6
|
+
|
7
|
+
errstatus=0
|
8
|
+
dirmode=""
|
9
|
+
|
10
|
+
usage="\
|
11
|
+
Usage: mkinstalldirs [-h] [--help] [-m mode] dir ..."
|
12
|
+
|
13
|
+
# process command line arguments
|
14
|
+
while test $# -gt 0 ; do
|
15
|
+
case "${1}" in
|
16
|
+
-h | --help | --h* ) # -h for help
|
17
|
+
echo "${usage}" 1>&2; exit 0 ;;
|
18
|
+
-m ) # -m PERM arg
|
19
|
+
shift
|
20
|
+
test $# -eq 0 && { echo "${usage}" 1>&2; exit 1; }
|
21
|
+
dirmode="${1}"
|
22
|
+
shift ;;
|
23
|
+
-- ) shift; break ;; # stop option processing
|
24
|
+
-* ) echo "${usage}" 1>&2; exit 1 ;; # unknown option
|
25
|
+
* ) break ;; # first non-opt arg
|
26
|
+
esac
|
27
|
+
done
|
28
|
+
|
29
|
+
for file
|
30
|
+
do
|
31
|
+
if test -d "$file"; then
|
32
|
+
shift
|
33
|
+
else
|
34
|
+
break
|
35
|
+
fi
|
36
|
+
done
|
37
|
+
|
38
|
+
case $# in
|
39
|
+
0) exit 0 ;;
|
40
|
+
esac
|
41
|
+
|
42
|
+
case $dirmode in
|
43
|
+
'')
|
44
|
+
if mkdir -p -- . 2>/dev/null; then
|
45
|
+
echo "mkdir -p -- $*"
|
46
|
+
exec mkdir -p -- "$@"
|
47
|
+
fi ;;
|
48
|
+
*)
|
49
|
+
if mkdir -m "$dirmode" -p -- . 2>/dev/null; then
|
50
|
+
echo "mkdir -m $dirmode -p -- $*"
|
51
|
+
exec mkdir -m "$dirmode" -p -- "$@"
|
52
|
+
fi ;;
|
53
|
+
esac
|
54
|
+
|
55
|
+
for file
|
56
|
+
do
|
57
|
+
set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'`
|
58
|
+
shift
|
59
|
+
|
60
|
+
pathcomp=
|
61
|
+
for d
|
62
|
+
do
|
63
|
+
pathcomp="$pathcomp$d"
|
64
|
+
case "$pathcomp" in
|
65
|
+
-* ) pathcomp=./$pathcomp ;;
|
66
|
+
esac
|
67
|
+
|
68
|
+
if test ! -d "$pathcomp"; then
|
69
|
+
echo "mkdir $pathcomp"
|
70
|
+
|
71
|
+
mkdir "$pathcomp" || lasterr=$?
|
72
|
+
|
73
|
+
if test ! -d "$pathcomp"; then
|
74
|
+
errstatus=$lasterr
|
75
|
+
else
|
76
|
+
if test ! -z "$dirmode"; then
|
77
|
+
echo "chmod $dirmode $pathcomp"
|
78
|
+
|
79
|
+
lasterr=""
|
80
|
+
chmod "$dirmode" "$pathcomp" || lasterr=$?
|
81
|
+
|
82
|
+
if test ! -z "$lasterr"; then
|
83
|
+
errstatus=$lasterr
|
84
|
+
fi
|
85
|
+
fi
|
86
|
+
fi
|
87
|
+
fi
|
88
|
+
|
89
|
+
pathcomp="$pathcomp/"
|
90
|
+
done
|
91
|
+
done
|
92
|
+
|
93
|
+
exit $errstatus
|
94
|
+
|
95
|
+
# Local Variables:
|
96
|
+
# mode: shell-script
|
97
|
+
# sh-indentation: 3
|
98
|
+
# End:
|
99
|
+
# mkinstalldirs ends here
|
100
|
+
|
@@ -0,0 +1,266 @@
|
|
1
|
+
#include <stdlib.h>
|
2
|
+
|
3
|
+
#include "qp_util.h"
|
4
|
+
#include "qp_frame.h"
|
5
|
+
|
6
|
+
qp_frame_context* qp_alloc_frame_ctx(qp_malloc_t malloc_func)
|
7
|
+
{
|
8
|
+
qp_frame_context *frame = NULL;
|
9
|
+
|
10
|
+
qp_malloc_t malloc_function = malloc_func ? malloc_func : malloc;
|
11
|
+
|
12
|
+
frame = (qp_frame_context *)malloc_function(sizeof(qp_frame_context));
|
13
|
+
|
14
|
+
if (!frame) {
|
15
|
+
return NULL;
|
16
|
+
}
|
17
|
+
|
18
|
+
frame->av_frame = NULL;
|
19
|
+
frame->width = 0;
|
20
|
+
frame->height = 0;
|
21
|
+
frame->pixel_format = 0;
|
22
|
+
|
23
|
+
return frame;
|
24
|
+
}
|
25
|
+
|
26
|
+
|
27
|
+
void qp_free_av_frame(AVFrame *av_frame)
|
28
|
+
{
|
29
|
+
if (av_frame) {
|
30
|
+
if (av_frame->data[0]) {
|
31
|
+
av_free(av_frame->data[0]);
|
32
|
+
}
|
33
|
+
av_free(av_frame);
|
34
|
+
av_frame = NULL;
|
35
|
+
}
|
36
|
+
}
|
37
|
+
|
38
|
+
|
39
|
+
void qp_free_frame_ctx(qp_frame_context *frame, qp_free_t free_func)
|
40
|
+
{
|
41
|
+
qp_free_t free_function = free_func ? free_func : free;
|
42
|
+
qp_free_av_frame(frame->av_frame);
|
43
|
+
free_function(frame);
|
44
|
+
}
|
45
|
+
|
46
|
+
|
47
|
+
int qp_get_frame_height(qp_frame_context *frame)
|
48
|
+
{
|
49
|
+
if(frame) {
|
50
|
+
return frame->height;
|
51
|
+
}
|
52
|
+
return 0;
|
53
|
+
}
|
54
|
+
|
55
|
+
int qp_get_frame_width(qp_frame_context *frame)
|
56
|
+
{
|
57
|
+
if(frame) {
|
58
|
+
return frame->width;
|
59
|
+
}
|
60
|
+
return 0;
|
61
|
+
}
|
62
|
+
|
63
|
+
|
64
|
+
const char* qp_get_frame_pixel_format_name(qp_frame_context *frame_ctx)
|
65
|
+
{
|
66
|
+
const char *fmt = avcodec_get_pix_fmt_name(frame_ctx->pixel_format);
|
67
|
+
|
68
|
+
if (fmt) {
|
69
|
+
return fmt;
|
70
|
+
} else {
|
71
|
+
return NULL;
|
72
|
+
}
|
73
|
+
}
|
74
|
+
|
75
|
+
|
76
|
+
|
77
|
+
int qp_convert_av_frame(AVFrame **av_frame, int pixel_format,
|
78
|
+
int new_format, int width, int height, int free_buffers)
|
79
|
+
{
|
80
|
+
AVFrame *new_format_frame = avcodec_alloc_frame();
|
81
|
+
AVFrame *old_format_frame = *av_frame;
|
82
|
+
|
83
|
+
avpicture_alloc((AVPicture*)new_format_frame, new_format, width, height);
|
84
|
+
if (img_convert((AVPicture*)new_format_frame, new_format,
|
85
|
+
(AVPicture *)old_format_frame, pixel_format, width, height) < 0) {
|
86
|
+
return -1;
|
87
|
+
}
|
88
|
+
|
89
|
+
*av_frame = new_format_frame;
|
90
|
+
|
91
|
+
if (free_buffers) {
|
92
|
+
qp_free_av_frame(old_format_frame);
|
93
|
+
} else {
|
94
|
+
/* free av_frame struct but leave buffers intact. This is needed
|
95
|
+
in the case where buffers are managed by the decoder. */
|
96
|
+
free(old_format_frame);
|
97
|
+
}
|
98
|
+
|
99
|
+
return 0;
|
100
|
+
}
|
101
|
+
|
102
|
+
|
103
|
+
int qp_convert_frame(qp_frame_context *frame, int new_pixel_format)
|
104
|
+
{
|
105
|
+
if (!frame->av_frame) {
|
106
|
+
return -1;
|
107
|
+
}
|
108
|
+
|
109
|
+
/* Don't convert if new format is the same as current. */
|
110
|
+
if (frame->pixel_format == new_pixel_format) {
|
111
|
+
return 0;
|
112
|
+
}
|
113
|
+
|
114
|
+
if (qp_convert_av_frame(&frame->av_frame, frame->pixel_format,
|
115
|
+
new_pixel_format, frame->width, frame->height, 1) != 0) {
|
116
|
+
return -2;
|
117
|
+
}
|
118
|
+
|
119
|
+
frame->pixel_format = new_pixel_format;
|
120
|
+
return 0;
|
121
|
+
}
|
122
|
+
|
123
|
+
|
124
|
+
int qp_crop_frame(qp_frame_context *frame,
|
125
|
+
int crop_top, int crop_bottom, int crop_left, int crop_right)
|
126
|
+
{
|
127
|
+
AVFrame *cropped_frame, *tmp_src;
|
128
|
+
AVFrame crop_temp;
|
129
|
+
int cropped_width, cropped_height;
|
130
|
+
|
131
|
+
if (!frame->av_frame) {
|
132
|
+
return -1;
|
133
|
+
}
|
134
|
+
|
135
|
+
tmp_src =frame->av_frame;
|
136
|
+
|
137
|
+
crop_temp.data[0] = tmp_src->data[0] +
|
138
|
+
(crop_top * tmp_src->linesize[0]) + crop_left;
|
139
|
+
|
140
|
+
crop_temp.data[1] = tmp_src->data[1] +
|
141
|
+
((crop_top >> 1) * tmp_src->linesize[1]) +
|
142
|
+
(crop_left >> 1);
|
143
|
+
|
144
|
+
crop_temp.data[2] = tmp_src->data[2] +
|
145
|
+
((crop_top >> 1) * tmp_src->linesize[2]) +
|
146
|
+
(crop_left >> 1);
|
147
|
+
|
148
|
+
crop_temp.linesize[0] = tmp_src->linesize[0];
|
149
|
+
crop_temp.linesize[1] = tmp_src->linesize[1];
|
150
|
+
crop_temp.linesize[2] = tmp_src->linesize[2];
|
151
|
+
|
152
|
+
cropped_frame = avcodec_alloc_frame();
|
153
|
+
|
154
|
+
cropped_width = frame->width - (crop_left + crop_right);
|
155
|
+
cropped_height = frame->height - (crop_top + crop_bottom);
|
156
|
+
|
157
|
+
avpicture_alloc((AVPicture*)cropped_frame, frame->pixel_format,
|
158
|
+
cropped_width, cropped_height);
|
159
|
+
|
160
|
+
img_copy((AVPicture*)cropped_frame,
|
161
|
+
(AVPicture *)&crop_temp, frame->pixel_format,
|
162
|
+
cropped_width, cropped_height);
|
163
|
+
|
164
|
+
/* free original uncropped frame */
|
165
|
+
qp_free_av_frame(frame->av_frame);
|
166
|
+
|
167
|
+
frame->av_frame = cropped_frame;
|
168
|
+
frame->width = cropped_width;
|
169
|
+
frame->height = cropped_height;
|
170
|
+
return 0;
|
171
|
+
}
|
172
|
+
|
173
|
+
|
174
|
+
int qp_resample_frame(qp_frame_context *frame,
|
175
|
+
int wanted_width, int wanted_height, int crop_top, int crop_bottom,
|
176
|
+
int crop_left, int crop_right)
|
177
|
+
{
|
178
|
+
AVFrame *resampled_frame;
|
179
|
+
ImgReSampleContext *img_resample_ctx = NULL;
|
180
|
+
|
181
|
+
if (!frame->av_frame) {
|
182
|
+
return -1;
|
183
|
+
}
|
184
|
+
|
185
|
+
/*
|
186
|
+
* do nothing if width and height are the same as the frame and no
|
187
|
+
* cropping was specified
|
188
|
+
*/
|
189
|
+
if (wanted_width == frame->width &&
|
190
|
+
wanted_height == frame->height &&
|
191
|
+
(!crop_left && !crop_right && !crop_top && !crop_bottom)) {
|
192
|
+
return 0;
|
193
|
+
}
|
194
|
+
|
195
|
+
/* just crop if wanted dimensions - crop bands = same width/height */
|
196
|
+
if (wanted_width == frame->width - (crop_left + crop_right) &&
|
197
|
+
wanted_height == frame->height - (crop_left + crop_right)) {
|
198
|
+
qp_crop_frame(frame, crop_top, crop_bottom, crop_left, crop_right);
|
199
|
+
return 0;
|
200
|
+
}
|
201
|
+
|
202
|
+
/* convert to PIX_FMT_YUV420P required for resampling */
|
203
|
+
qp_convert_frame(frame, PIX_FMT_YUV420P);
|
204
|
+
|
205
|
+
img_resample_ctx = img_resample_full_init(
|
206
|
+
wanted_width, wanted_height,
|
207
|
+
frame->width, frame->height,
|
208
|
+
crop_top, crop_bottom, crop_left, crop_right,
|
209
|
+
0, 0, 0, 0);
|
210
|
+
if (!img_resample_ctx) {
|
211
|
+
return -1;
|
212
|
+
}
|
213
|
+
|
214
|
+
resampled_frame = avcodec_alloc_frame();
|
215
|
+
avpicture_alloc((AVPicture*)resampled_frame, PIX_FMT_YUV420P,
|
216
|
+
wanted_width, wanted_height);
|
217
|
+
|
218
|
+
img_resample(img_resample_ctx, (AVPicture*)resampled_frame,
|
219
|
+
(AVPicture*)frame->av_frame);
|
220
|
+
|
221
|
+
qp_free_av_frame(frame->av_frame);
|
222
|
+
|
223
|
+
img_resample_close(img_resample_ctx);
|
224
|
+
|
225
|
+
frame->av_frame = resampled_frame;
|
226
|
+
frame->width = wanted_width;
|
227
|
+
frame->height = wanted_height;
|
228
|
+
|
229
|
+
return 0;
|
230
|
+
}
|
231
|
+
|
232
|
+
|
233
|
+
/*
|
234
|
+
* output_as_string - create a packed RGB24 string from this frame's data in
|
235
|
+
* char_ptr. It is the caller's resposibility to free char_ptr.
|
236
|
+
*/
|
237
|
+
int qp_output_frame_as_string(qp_frame_context *frame, unsigned char **char_ptr)
|
238
|
+
{
|
239
|
+
AVFrame *new_format_frame = avcodec_alloc_frame();
|
240
|
+
|
241
|
+
avpicture_alloc((AVPicture*)new_format_frame, PIX_FMT_RGB24,
|
242
|
+
frame->width, frame->height);
|
243
|
+
|
244
|
+
if (img_convert((AVPicture*)new_format_frame, PIX_FMT_RGB24,
|
245
|
+
(AVPicture *)frame->av_frame, frame->pixel_format,
|
246
|
+
frame->width, frame->height) < 0) {
|
247
|
+
return -1;
|
248
|
+
}
|
249
|
+
|
250
|
+
*char_ptr = new_format_frame->data[0];
|
251
|
+
|
252
|
+
/* free the frame struct that was allocated by avcodec_alloc_frame. This will
|
253
|
+
not free the actual frame data that we are returning. */
|
254
|
+
free(new_format_frame);
|
255
|
+
|
256
|
+
return avpicture_get_size(PIX_FMT_RGB24, frame->width, frame->height);
|
257
|
+
}
|
258
|
+
|
259
|
+
|
260
|
+
double qp_get_pts(qp_frame_context *frame) {
|
261
|
+
return ((double)frame->pts / AV_TIME_BASE);
|
262
|
+
}
|
263
|
+
|
264
|
+
long qp_frame_is_keyframe(qp_frame_context *frame) {
|
265
|
+
return (long)frame->keyframe;
|
266
|
+
}
|