rmovie 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
+
}
|