Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- Index: Makefile
- ===================================================================
- --- Makefile_orig
- +++ Makefile
- @@ -13,10 +13,11 @@
- encoder/set.c encoder/macroblock.c encoder/cabac.c \
- encoder/cavlc.c encoder/encoder.c encoder/lookahead.c
- -SRCCLI = x264.c input/timecode.c \
- - input/yuv.c input/y4m.c output/raw.c \
- - output/matroska.c output/matroska_ebml.c \
- - output/flv.c output/flv_bytestream.c
- +SRCCLI = x264.c input/common.c input/timecode.c input/raw.c input/y4m.c \
- + output/raw.c output/matroska.c output/matroska_ebml.c \
- + output/flv.c output/flv_bytestream.c filter/source.c \
- + filter/filter.c filter/cache.c filter/select_every.c \
- + filter/resize.c filter/utils.c filter/fix_vfr_pts.c
- SRCSO =
- @@ -132,7 +133,7 @@
- $(CC) -shared -o $@ $(OBJS) $(OBJASM) $(OBJSO) $(SOFLAGS) $(LDFLAGS)
- x264$(EXE): $(OBJCLI) libx264.a
- - $(CC) -o $@ $+ $(LDFLAGS) $(LDFLAGSCLI)
- + $(CC) -o $@ $+ $(LDFLAGSCLI) $(LDFLAGS)
- checkasm: tools/checkasm.o libx264.a
- $(CC) -o $@ $+ $(LDFLAGS)
- Index: common/common.c
- ===================================================================
- --- common/common_orig.c
- +++ common/common.c
- @@ -1001,8 +1001,7 @@
- ****************************************************************************/
- int x264_picture_alloc( x264_picture_t *pic, int i_csp, int i_width, int i_height )
- {
- - pic->i_type = X264_TYPE_AUTO;
- - pic->i_qpplus1 = 0;
- + x264_picture_defaults( pic );
- pic->img.i_csp = i_csp;
- pic->img.i_plane = 3;
- pic->img.plane[0] = x264_malloc( 3 * i_width * i_height / 2 );
- @@ -1013,9 +1012,18 @@
- pic->img.i_stride[0] = i_width;
- pic->img.i_stride[1] = i_width / 2;
- pic->img.i_stride[2] = i_width / 2;
- + return 0;
- +}
- +
- +/****************************************************************************
- + * x264_picture_defaults:
- + ****************************************************************************/
- +void x264_picture_defaults( x264_picture_t *pic )
- +{
- + pic->i_type = X264_TYPE_AUTO;
- + pic->i_qpplus1 = 0;
- pic->param = NULL;
- pic->i_pic_struct = PIC_STRUCT_AUTO;
- - return 0;
- }
- /****************************************************************************
- Index: configure
- ===================================================================
- --- configure_orig
- +++ configure
- @@ -13,6 +13,7 @@
- echo " --disable-mp4-output disables mp4 output (using gpac)"
- echo " --disable-avi-output disables avi output (using libavformat)"
- echo " --disable-pthread disables multithreaded encoding"
- +echo " --disable-swscale disables swscale support"
- echo " --disable-asm disables platform-specific assembly optimizations"
- echo " --enable-debug adds -g, doesn't strip"
- echo " --enable-gprof adds -pg, doesn't strip"
- @@ -62,7 +63,7 @@
- rm -f conftest.c
- [ -n "$1" ] && echo "#include <$1>" > conftest.c
- echo "int main () { $3 return 0; }" >> conftest.c
- - if $CC conftest.c $CFLAGS $LDFLAGS $LDFLAGSCLI $2 -o conftest >conftest.log 2>&1; then
- + if $CC conftest.c $CFLAGS $2 $LDFLAGSCLI $LDFLAGS -o conftest >conftest.log 2>&1; then
- res=$?
- log_ok
- else
- @@ -77,6 +78,25 @@
- return $res
- }
- +cpp_check() {
- + log_check "whether $3 is true"
- + rm -f conftest.c
- + [ -n "$1" ] && echo "#include <$1>" > conftest.c
- + echo -e "#if !($3) \n#error $4 \n#endif " >> conftest.c
- +
- + if $CC conftest.c $CFLAGS $2 $LDFLAGSCLI $LDFLAGS -E -o conftest >conftest.log 2>&1; then
- + res=$?
- + log_ok
- + else
- + res=$?
- + log_fail
- + log_msg "--------------------------------------------------"
- + cat conftest.log >> config.log
- + log_msg "--------------------------------------------------"
- + fi
- + return $res
- +}
- +
- as_check() {
- log_check "whether $AS supports $1"
- echo "$1" > conftest.asm
- @@ -120,6 +140,7 @@
- mp4_output="auto"
- avi_output="auto"
- pthread="auto"
- +swscale="auto"
- asm="auto"
- debug="no"
- gprof="no"
- @@ -189,6 +210,12 @@
- --disable-pthread)
- pthread="no"
- ;;
- + --enable-swscale)
- + swscale="auto"
- + ;;
- + --disable-swscale)
- + swscale="no"
- + ;;
- --enable-debug)
- debug="yes"
- ;;
- @@ -512,6 +539,25 @@
- vis="no"
- fi
- +if [ $swscale = auto ] ; then
- + swscale=no
- + if ${cross_prefix}pkg-config --exists libswscale 2>$DEVNULL; then
- + SWSCALE_LIBS="$SWSCALE_LIBS $(${cross_prefix}pkg-config --libs libswscale)"
- + SWSCALE_CFLAGS="$SWSCALE_CFLAGS $(${cross_prefix}pkg-config --cflags libswscale)"
- + fi
- + [ -z "$SWSCALE_LIBS" ] && SWSCALE_LIBS="-lswscale -lavutil"
- +
- + error="swscale must be at least version 0.9.0"
- + if cc_check "libswscale/swscale.h" "$SWSCALE_CFLAGS $SWSCALE_LIBS" "sws_getContext(0,0,0,0,0,0,0,0,0,0);" ; then
- + if cpp_check "libswscale/swscale.h" "$SWSCALE_CFLAGS" "LIBSWSCALE_VERSION_INT >= AV_VERSION_INT(0,9,0)" "$error"; then
- + define HAVE_SWSCALE
- + swscale=yes
- + else
- + echo "Warning: ${error}"
- + fi
- + fi
- +fi
- +
- if [ "$lavf_input" = "auto" ] ; then
- lavf_input="no"
- if ${cross_prefix}pkg-config --exists libavformat libavcodec libswscale 2>$DEVNULL; then
- @@ -519,18 +565,21 @@
- LAVF_CFLAGS="$LAVF_CFLAGS $(${cross_prefix}pkg-config --cflags libavformat libavcodec libswscale)"
- fi
- if [ -z "$LAVF_LIBS" -a -z "$LAVF_CFLAGS" ]; then
- - LAVF_LIBS="-lavformat -lswscale"
- - for lib in -lpostproc -lavcodec -lavutil -lm -lz -lbz2 $libpthread -lavifil32; do
- + LAVF_LIBS="-lavformat"
- + for lib in -lavcodec -lpostproc -lswscale -lavutil -lz -lbz2 -lavifil32; do
- cc_check "" $lib && LAVF_LIBS="$LAVF_LIBS $lib"
- done
- fi
- LAVF_LIBS="-L. $LAVF_LIBS"
- - if cc_check libavformat/avformat.h "$LAVF_CFLAGS $LAVF_LIBS" && \
- - cc_check libswscale/swscale.h "$LAVF_CFLAGS $LAVF_LIBS" ; then
- + if cc_check libavformat/avformat.h "$LAVF_CFLAGS $LAVF_LIBS" ; then
- # avcodec_decode_video2 is currently the most recently added function that we use; it was added in r18351
- if cc_check libavformat/avformat.h "$LAVF_CFLAGS $LAVF_LIBS" "avcodec_decode_video2( NULL, NULL, NULL, NULL );" ; then
- - lavf_input="yes"
- - define LAVF_INPUT
- + if [ "$swscale" = "yes" ]; then
- + lavf_input="yes"
- + define LAVF_INPUT
- + else
- + echo "Warning: libavformat is not supported without swscale support"
- + fi
- else
- echo "Warning: libavformat is too old, update to ffmpeg r18351+"
- fi
- @@ -559,15 +608,15 @@
- FFMS2_LIBS="$FFMS2_LIBS -lstdc++ $LAVF_LIBS"
- fi
- - if [ $api_check = "yes" -a $ffms_input = "yes" ]; then
- - log_check "whether ffms2 version is at least $ffms_major.$ffms_minor$vmicro$vbump"
- - $CC $CFLAGS $FFMS2_CFLAGS -c -o conftest -x c - >$DEVNULL 2>&1 <<EOF
- -#include <ffms.h>
- -#if FFMS_VERSION < (($ffms_major << 24) | ($ffms_minor << 16) | ($ffms_micro << 8) | $ffms_bump)
- -#error Requires ffms2 version 2.13.1
- -#endif
- -EOF
- - [ $? = 0 ] && log_ok || { ffms_input="no"; log_fail; }
- + error="ffms2 must be at least version 2.13.1"
- + if [ $api_check = "yes" -a $ffms_input = "yes" ] &&
- + ! cpp_check "ffms.h" "$FFMS_CFLAGS" "FFMS_VERSION >= (($ffms_major << 24) | ($ffms_minor << 16) | ($ffms_micro << 8) | $ffms_bump)" "$error"; then
- + ffms_input="no"
- + echo "Warning: $error"
- + fi
- + if [ "$ffms_input" = "yes" -a "$swscale" = "no" ]; then
- + echo "Warning: ffms is not supported without swscale support"
- + ffms_input="no"
- fi
- fi
- @@ -578,6 +627,9 @@
- elif [ "$lavf_input" = "yes" ]; then
- LDFLAGSCLI="$LAVF_LIBS $LDFLAGSCLI"
- [ -n "$LAVF_CFLAGS" ] && CFLAGS="$CFLAGS $LAVF_CFLAGS"
- +elif [ "$swscale" = "yes" ]; then
- + LDFLAGSCLI="$SWSCALE_LIBS $LDFLAGSCLI"
- + [ -n "$SWSCALE_CFLAGS" ] && CFLAGS="$CFLAGS $SWSCALE_CFLAGS"
- fi
- MP4_LDFLAGS="-lgpac_static"
- @@ -736,6 +788,9 @@
- Cflags: -I$includedir
- EOF
- +filters="select_every"
- +[ $swscale = yes ] && filters="resize $filters"
- +
- cat > conftest.log <<EOF
- Platform: $ARCH
- System: $SYS
- @@ -746,6 +801,7 @@
- mp4 output: $mp4_output
- avi output: $avi_output
- pthread: $pthread
- +filters: $filters
- debug: $debug
- gprof: $gprof
- PIC: $pic
- Index: filter/cache.c
- ===================================================================
- --- /dev/null
- +++ filter/cache.c
- @@ -0,0 +1,142 @@
- +/*****************************************************************************
- + * cache.c: x264 cache filter
- + *****************************************************************************
- + * Copyright (C) 2010 Steven Walters <kemuri9@gmail.com>
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License as published by
- + * the Free Software Foundation; either version 2 of the License, or
- + * (at your option) any later version.
- + *
- + * This program 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 General Public License for more details.
- + *
- + * You should have received a copy of the GNU General Public License
- + * along with this program; if not, write to the Free Software
- + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111, USA.
- + *****************************************************************************/
- +
- +#include "filter.h"
- +#include "utils.h"
- +
- +#define LAST_FRAME (h->first_frame + h->cur_size - 1)
- +
- +typedef struct
- +{
- + hnd_t prev_hnd;
- + cli_vid_filter_t prev_filter;
- +
- + int max_size;
- + int first_frame; /* first cached frame */
- + cli_pic_t **cache;
- + int cur_size;
- + int eof; /* frame beyond end of the file */
- +} cache_hnd_t;
- +
- +cli_vid_filter_t cache_filter;
- +
- +static int init( hnd_t *handle, cli_vid_filter_t *filter, video_info_t *info, x264_param_t *param, char *opt_string )
- +{
- + intptr_t size = (intptr_t)opt_string;
- + /* upon a <= 0 cache request, do nothing */
- + if( size <= 0 )
- + return 0;
- + cache_hnd_t *h = calloc( 1, sizeof(cache_hnd_t) );
- + if( !h )
- + return -1;
- +
- + h->max_size = size;
- + h->cache = malloc( (h->max_size+1) * sizeof(cli_pic_t*) );
- + if( !h->cache )
- + return -1;
- +
- + for( int i = 0; i < h->max_size; i++ )
- + {
- + h->cache[i] = malloc( sizeof(cli_pic_t) );
- + if( !h->cache[i] || x264_cli_pic_alloc( h->cache[i], info->csp, info->width, info->height ) )
- + return -1;
- + }
- + h->cache[h->max_size] = NULL; /* require null terminator for list methods */
- +
- + h->prev_filter = *filter;
- + h->prev_hnd = *handle;
- + *handle = h;
- + *filter = cache_filter;
- +
- + return 0;
- +}
- +
- +static void fill_cache( cache_hnd_t *h, int frame )
- +{
- + /* shift frames out of the cache as the frame request is beyond the filled cache */
- + int shift = frame - LAST_FRAME;
- + /* no frames to shift or no frames left to read */
- + if( shift <= 0 || h->eof )
- + return;
- + /* the next frames to read are either
- + * A) starting at the end of the current cache, or
- + * B) starting at a new frame that has the end of the cache at the desired frame
- + * and proceeding to fill the entire cache */
- + int cur_frame = X264_MAX( h->first_frame + h->cur_size, frame - h->max_size + 1 );
- + /* the new starting point is either
- + * A) the current one shifted the number of frames entering/leaving the cache, or
- + * B) at a new frame that has the end of the cache at the desired frame. */
- + h->first_frame = X264_MIN( h->first_frame + shift, cur_frame );
- + h->cur_size = X264_MAX( h->cur_size - shift, 0 );
- + while( h->cur_size < h->max_size )
- + {
- + cli_pic_t temp;
- + /* the old front frame is going to shift off, overwrite it with the new frame */
- + cli_pic_t *cache = h->cache[0];
- + if( h->prev_filter.get_frame( h->prev_hnd, &temp, cur_frame ) ||
- + x264_cli_pic_copy( cache, &temp ) ||
- + h->prev_filter.release_frame( h->prev_hnd, &temp, cur_frame ) )
- + {
- + h->eof = cur_frame;
- + return;
- + }
- + /* the read was successful, shift the frame off the front to the end */
- + x264_frame_push( (void*)h->cache, x264_frame_shift( (void*)h->cache ) );
- + cur_frame++;
- + h->cur_size++;
- + }
- +}
- +
- +static int get_frame( hnd_t handle, cli_pic_t *output, int frame )
- +{
- + cache_hnd_t *h = handle;
- + if( frame < h->first_frame )
- + {
- + fprintf( stderr, "cache [error]: frame %d is before first cached frame %d \n", frame, h->first_frame );
- + return -1;
- + }
- + fill_cache( h, frame );
- + if( frame > LAST_FRAME ) /* eof */
- + return -1;
- + int idx = frame - (h->eof ? h->eof - h->max_size : h->first_frame);
- + *output = *h->cache[idx];
- + return 0;
- +}
- +
- +static int release_frame( hnd_t handle, cli_pic_t *pic, int frame )
- +{
- + /* the parent filter's frame has already been released so do nothing here */
- + return 0;
- +}
- +
- +static void free_filter( hnd_t handle )
- +{
- + cache_hnd_t *h = handle;
- + h->prev_filter.free( h->prev_hnd );
- + for( int i = 0; i < h->max_size; i++ )
- + {
- + x264_cli_pic_clean( h->cache[i] );
- + free( h->cache[i] );
- + }
- + free( h->cache );
- + free( h );
- +}
- +
- +cli_vid_filter_t cache_filter = { "cache", NULL, init, get_frame, release_frame, free_filter, NULL };
- Index: filter/filter.c
- ===================================================================
- --- /dev/null
- +++ filter/filter.c
- @@ -0,0 +1,73 @@
- +/*****************************************************************************
- + * filter.c: x264 filter driver
- + *****************************************************************************
- + * Copyright (C) 2010 Steven Walters <kemuri9@gmail.com>
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License as published by
- + * the Free Software Foundation; either version 2 of the License, or
- + * (at your option) any later version.
- + *
- + * This program 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 General Public License for more details.
- + *
- + * You should have received a copy of the GNU General Public License
- + * along with this program; if not, write to the Free Software
- + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111, USA.
- + *****************************************************************************/
- +
- +#include "filter.h"
- +
- +static cli_vid_filter_t *first_filter = NULL;
- +
- +static void register_vid_filter( cli_vid_filter_t *new_filter )
- +{
- + cli_vid_filter_t *filter_i = first_filter;
- + while( filter_i->next )
- + filter_i = filter_i->next;
- + filter_i->next = new_filter;
- + new_filter->next = NULL;
- +}
- +
- +#define REGISTER_VFILTER(name) \
- +{\
- + extern cli_vid_filter_t name##_filter;\
- + register_vid_filter( &name##_filter );\
- +}
- +
- +void x264_register_vid_filters()
- +{
- + extern cli_vid_filter_t source_filter;
- + first_filter = &source_filter;
- + //REGISTER_VFILTER( source );
- + REGISTER_VFILTER( cache );
- + REGISTER_VFILTER( fix_vfr_pts );
- + REGISTER_VFILTER( resize );
- + REGISTER_VFILTER( select_every );
- +}
- +
- +int x264_init_vid_filter( const char *name, hnd_t *handle, cli_vid_filter_t *filter,
- + video_info_t *info, x264_param_t *param, char *opt_string )
- +{
- + cli_vid_filter_t *filter_i = first_filter;
- + while( filter_i && strcasecmp( name, filter_i->name ) )
- + filter_i = filter_i->next;
- + if( !filter_i )
- + {
- + fprintf( stderr, "x264 [error]: invalid filter `%s'\n", name );
- + return -1;
- + }
- + if( filter_i->init( handle, filter, info, param, opt_string ) )
- + return -1;
- +
- + return 0;
- +}
- +
- +void x264_vid_filter_help( int longhelp )
- +{
- + for( cli_vid_filter_t *filter_i = first_filter; filter_i; filter_i = filter_i->next )
- + if( filter_i->help )
- + filter_i->help( longhelp );
- +}
- Index: filter/filter.h
- ===================================================================
- --- /dev/null
- +++ filter/filter.h
- @@ -0,0 +1,56 @@
- +/*****************************************************************************
- + * filter.h: x264 filter modules
- + *****************************************************************************
- + * Copyright (C) 2010 Steven Walters <kemuri9@gmail.com>
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License as published by
- + * the Free Software Foundation; either version 2 of the License, or
- + * (at your option) any later version.
- + *
- + * This program 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 General Public License for more details.
- + *
- + * You should have received a copy of the GNU General Public License
- + * along with this program; if not, write to the Free Software
- + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111, USA.
- + *****************************************************************************/
- +
- +#ifndef X264_FILTER_H
- +#define X264_FILTER_H
- +
- +#include "muxers.h"
- +
- +typedef struct cli_vid_filter_t cli_vid_filter_t;
- +
- +struct cli_vid_filter_t
- +{
- + /* name of the filter */
- + const char *name;
- + /* help: a short message on what the filter does and how to use it.
- + * this should only be implemented by filters directly accessible by the user */
- + void (*help)( int longhelp );
- + /* init: initializes the filter given the input clip properties and parameter to adjust them as necessary
- + * with the given options provided by the user.
- + * returns 0 on success, nonzero on error. */
- + int (*init)( hnd_t *handle, cli_vid_filter_t *filter, video_info_t *info, x264_param_t *param, char *opt_string );
- + /* get_frame: given the storage for the output frame and desired frame number, generate the frame accordingly.
- + * the image data returned by get_frame should be treated as const and not be altered.
- + * returns 0 on success, nonzero on error. */
- + int (*get_frame)( hnd_t handle, cli_pic_t *output, int frame );
- + /* release_frame: frame is done being used and is signaled for cleanup. */
- + int (*release_frame)( hnd_t handle, cli_pic_t *pic, int frame );
- + /* free: run filter cleanup procedures. */
- + void (*free)( hnd_t handle );
- + /* next registered filter, unused by filters themselves */
- + cli_vid_filter_t *next;
- +};
- +
- +void x264_register_vid_filters();
- +void x264_vid_filter_help( int longhelp );
- +int x264_init_vid_filter( const char *name, hnd_t *handle, cli_vid_filter_t *filter,
- + video_info_t *info, x264_param_t *param, char *opt_string );
- +
- +#endif
- Index: filter/fix_vfr_pts.c
- ===================================================================
- --- /dev/null
- +++ filter/fix_vfr_pts.c
- @@ -0,0 +1,126 @@
- +/*****************************************************************************
- + * fix_vfr_pts.c: x264 vfr pts fixing filter
- + *****************************************************************************
- + * Copyright (C) 2010 Steven Walters <kemuri9@gmail.com>
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License as published by
- + * the Free Software Foundation; either version 2 of the License, or
- + * (at your option) any later version.
- + *
- + * This program 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 General Public License for more details.
- + *
- + * You should have received a copy of the GNU General Public License
- + * along with this program; if not, write to the Free Software
- + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111, USA.
- + *****************************************************************************/
- +
- +#include "filter.h"
- +#include "utils.h"
- +
- +typedef struct
- +{
- + hnd_t prev_hnd;
- + cli_vid_filter_t prev_filter;
- +
- + /* we need 1 buffer picture and 1 place holder */
- + cli_pic_t buffer;
- + cli_pic_t holder;
- + int buffer_allocated;
- + int holder_frame;
- + int holder_ret;
- + int64_t pts;
- + int64_t last_duration;
- +} fix_vfr_pts_hnd_t;
- +
- +cli_vid_filter_t fix_vfr_pts_filter;
- +
- +static int init( hnd_t *handle, cli_vid_filter_t *filter, video_info_t *info, x264_param_t *param, char *opt_string )
- +{
- + /* if the input is not vfr, we don't do anything */
- + if( !info->vfr )
- + return 0;
- + fix_vfr_pts_hnd_t *h = calloc( 1, sizeof(fix_vfr_pts_hnd_t) );
- + if( !h )
- + return -1;
- +
- + h->holder_frame = -1;
- + h->prev_hnd = *handle;
- + h->prev_filter = *filter;
- + *handle = h;
- + *filter = fix_vfr_pts_filter;
- +
- + return 0;
- +}
- +
- +static int get_frame( hnd_t handle, cli_pic_t *output, int frame )
- +{
- + fix_vfr_pts_hnd_t *h = handle;
- + /* if we want the holder picture and it errored, return the error. */
- + if( frame == h->holder_frame )
- + {
- + if( h->holder_ret )
- + return h->holder_ret;
- + }
- + else
- + {
- + /* if we have a holder frame and we don't want it, release the frame */
- + if( h->holder_frame > 0 && h->holder_frame < frame && h->prev_filter.release_frame( h->prev_hnd, &h->holder, h->holder_frame ) )
- + return -1;
- + h->holder_frame = -1;
- + if( h->prev_filter.get_frame( h->prev_hnd, &h->holder, frame ) )
- + return -1;
- + }
- +
- + /* if the frame's duration is not set already, read the next frame to set it. */
- + if( !h->holder.duration )
- + {
- + /* allocate a buffer picture if we didn't already */
- + if( !h->buffer_allocated )
- + {
- + if( x264_cli_pic_alloc( &h->buffer, h->holder.img.csp, h->holder.img.width, h->holder.img.height ) )
- + return -1;
- + h->buffer_allocated = 1;
- + }
- + h->holder_frame = frame+1;
- + /* copy the current frame to the buffer, release it, and then read in the next frame to the placeholder */
- + if( x264_cli_pic_copy( &h->buffer, &h->holder ) || h->prev_filter.release_frame( h->prev_hnd, &h->holder, frame ) )
- + return -1;
- + h->holder_ret = h->prev_filter.get_frame( h->prev_hnd, &h->holder, h->holder_frame );
- + /* suppress non-monotonic pts warnings by setting the duration to be at least 1 */
- + if( !h->holder_ret )
- + h->last_duration = X264_MAX( h->holder.pts - h->buffer.pts, 1 );
- + h->buffer.duration = h->last_duration;
- + *output = h->buffer;
- + }
- + else
- + *output = h->holder;
- +
- + output->pts = h->pts;
- + h->pts += output->duration;
- +
- + return 0;
- +}
- +
- +static int release_frame( hnd_t handle, cli_pic_t *pic, int frame )
- +{
- + fix_vfr_pts_hnd_t *h = handle;
- + /* if the frame is the buffered one, it's already been released */
- + if( frame == (h->holder_frame - 1) )
- + return 0;
- + return h->prev_filter.release_frame( h->prev_hnd, pic, frame );
- +}
- +
- +static void free_filter( hnd_t handle )
- +{
- + fix_vfr_pts_hnd_t *h = handle;
- + h->prev_filter.free( h->prev_hnd );
- + if( h->buffer_allocated )
- + x264_cli_pic_clean( &h->buffer );
- + free( h );
- +}
- +
- +cli_vid_filter_t fix_vfr_pts_filter = { "fix_vfr_pts", NULL, init, get_frame, release_frame, free_filter, NULL };
- Index: filter/resize.c
- ===================================================================
- --- /dev/null
- +++ filter/resize.c
- @@ -0,0 +1,347 @@
- +/*****************************************************************************
- + * resize.c: x264 resize filter
- + *****************************************************************************
- + * Copyright (C) 2010 Steven Walters <kemuri9@gmail.com>
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License as published by
- + * the Free Software Foundation; either version 2 of the License, or
- + * (at your option) any later version.
- + *
- + * This program 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 General Public License for more details.
- + *
- + * You should have received a copy of the GNU General Public License
- + * along with this program; if not, write to the Free Software
- + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111, USA.
- + *****************************************************************************/
- +
- +#include "filter.h"
- +
- +cli_vid_filter_t resize_filter;
- +
- +static int csp_check( video_info_t *info );
- +
- +static int full_check( video_info_t *info, x264_param_t *param )
- +{
- + int required = 0;
- + required |= csp_check( info );
- + required |= info->width != param->i_width;
- + required |= info->height != param->i_height;
- + return required;
- +}
- +
- +#ifdef HAVE_SWSCALE
- +#undef DECLARE_ALIGNED
- +#include <libswscale/swscale.h>
- +
- +/* this function is not a part of the swscale API but is defined in swscale_internal.h */
- +const char *sws_format_name( enum PixelFormat format );
- +
- +extern cli_input_t input;
- +
- +typedef struct
- +{
- + int width;
- + int height;
- + int pix_fmt;
- +} frame_prop_t;
- +
- +typedef struct
- +{
- + hnd_t prev_hnd;
- + cli_vid_filter_t prev_filter;
- +
- + cli_pic_t buffer;
- + int buffer_allocated;
- + int dst_csp;
- + struct SwsContext *ctx;
- + int ctx_flags;
- + frame_prop_t dst; /* desired output properties */
- + frame_prop_t scale; /* properties of the SwsContext input */
- +} resizer_hnd_t;
- +
- +static void help( int longhelp )
- +{
- + printf( " resize:widthxheight[,method]\n" );
- + if( !longhelp )
- + return;
- + printf( " resizes frames to the given size using resizer [\"bicubic\"]\n"
- + " - fastbilinear, bilinear, bicubic, experimental, point,\n"
- + " - area, bicublin, gauss, sinc, lanczos, spline\n" );
- +}
- +
- +static uint32_t convert_cpu_to_flag( uint32_t cpu )
- +{
- + uint32_t swscale_cpu = 0;
- + if( cpu & X264_CPU_ALTIVEC )
- + swscale_cpu |= SWS_CPU_CAPS_ALTIVEC;
- + if( cpu & X264_CPU_MMXEXT )
- + swscale_cpu |= SWS_CPU_CAPS_MMX | SWS_CPU_CAPS_MMX2;
- + return swscale_cpu;
- +}
- +
- +static uint32_t convert_method_to_flag( const char *name )
- +{
- + uint32_t flag = 0;
- + name += *name == ',';
- + if( !strcasecmp( name, "fastbilinear" ) )
- + flag = SWS_FAST_BILINEAR;
- + else if( !strcasecmp( name, "bilinear" ) )
- + flag = SWS_BILINEAR;
- + else if( !strcasecmp( name, "bicubic" ) )
- + flag = SWS_BICUBIC;
- + else if( !strcasecmp( name, "experimental" ) )
- + flag = SWS_X;
- + else if( !strcasecmp( name, "point" ) )
- + flag = SWS_POINT;
- + else if( !strcasecmp( name, "area" ) )
- + flag = SWS_AREA;
- + else if( !strcasecmp( name, "bicublin" ) )
- + flag = SWS_BICUBLIN;
- + else if( !strcasecmp( name, "guass" ) )
- + flag = SWS_GAUSS;
- + else if( !strcasecmp( name, "sinc" ) )
- + flag = SWS_SINC;
- + else if( !strcasecmp( name, "lanczos" ) )
- + flag = SWS_LANCZOS;
- + else if( !strcasecmp( name, "spline" ) )
- + flag = SWS_SPLINE;
- + else // default
- + flag = SWS_BICUBIC;
- + return flag;
- +}
- +
- +static int convert_csp_to_pix_fmt( int csp )
- +{
- + if( csp&X264_CSP_OTHER )
- + return csp&X264_CSP_MASK;
- + switch( csp&X264_CSP_MASK )
- + {
- + case X264_CSP_I420: return PIX_FMT_YUV420P;
- + case X264_CSP_I422: return PIX_FMT_YUV422P;
- + case X264_CSP_I444: return PIX_FMT_YUV444P;
- + case X264_CSP_YV12: return PIX_FMT_NONE; /* planar yvu 4:2:0 is not supported by libswscale */
- + case X264_CSP_BGR: return PIX_FMT_BGR24;
- + case X264_CSP_BGRA: return PIX_FMT_BGRA;
- + default: return PIX_FMT_NONE;
- + }
- +}
- +
- +static int pick_closest_supported_csp( int csp )
- +{
- + int pix_fmt = convert_csp_to_pix_fmt( csp );
- + switch( pix_fmt )
- + {
- + case PIX_FMT_YUV422P:
- + case PIX_FMT_YUV422P16LE:
- + case PIX_FMT_YUV422P16BE:
- + case PIX_FMT_YUYV422: // convert yuyv to 422p
- + case PIX_FMT_UYVY422:
- + return X264_CSP_I422;
- + case PIX_FMT_YUV444P:
- + case PIX_FMT_YUV444P16LE:
- + case PIX_FMT_YUV444P16BE:
- + return X264_CSP_I444;
- + case PIX_FMT_RGB24: // convert rgb to bgr
- + case PIX_FMT_RGB48BE:
- + case PIX_FMT_RGB48LE:
- + case PIX_FMT_RGB565BE:
- + case PIX_FMT_RGB565LE:
- + case PIX_FMT_RGB555BE:
- + case PIX_FMT_RGB555LE:
- + case PIX_FMT_BGR24:
- + case PIX_FMT_BGR565BE:
- + case PIX_FMT_BGR565LE:
- + case PIX_FMT_BGR555BE:
- + case PIX_FMT_BGR555LE:
- + return X264_CSP_BGR;
- + case PIX_FMT_ARGB:
- + case PIX_FMT_RGBA:
- + case PIX_FMT_ABGR:
- + case PIX_FMT_BGRA:
- + return X264_CSP_BGRA;
- + default:
- + return X264_CSP_I420;
- + }
- +}
- +
- +static int init( hnd_t *handle, cli_vid_filter_t *filter, video_info_t *info, x264_param_t *param, char *opt_string )
- +{
- + /* if called for csp conversion and no csp conversion is necessary, exit */
- + if( opt_string && !strcmp( opt_string, "csp" ) && !csp_check( info ) )
- + return 0;
- + /* if called for normalizing the csp to known formats and the format is not unknown, exit */
- + if( opt_string && !strcmp( opt_string, "normcsp" ) && !(info->csp&X264_CSP_OTHER) )
- + return 0;
- + /* if called by x264cli and nothing needs to be done, exit */
- + if( !opt_string && !full_check( info, param ) )
- + return 0;
- +
- + resizer_hnd_t *h = calloc( 1, sizeof(resizer_hnd_t) );
- + if( !h )
- + return -1;
- + h->dst_csp = info->dst_csp;
- + if( opt_string )
- + {
- + int len = 0;
- + h->dst.height = info->height;
- + h->dst.width = info->width;
- + if( !strcmp( opt_string, "csp" ) )
- + ;
- + else if( !strcmp( opt_string, "normcsp" ) )
- + h->dst_csp = pick_closest_supported_csp( info->csp );
- + else if( sscanf( opt_string, "%ux%u%n", &h->dst.width, &h->dst.height, &len ) != 2 )
- + {
- + fprintf( stderr, "resize [error]: invalid resolution %s\n", opt_string );
- + return -1;
- + }
- + opt_string += len;
- + }
- + else
- + {
- + h->dst.width = param->i_width;
- + h->dst.height = param->i_height;
- + opt_string = "";
- + }
- + /* cpu flags + no quick cheats + method */
- + h->ctx_flags = convert_cpu_to_flag( param->cpu ) | SWS_FULL_CHR_H_INP | SWS_FULL_CHR_H_INT
- + | SWS_BITEXACT | SWS_ACCURATE_RND | convert_method_to_flag( opt_string );
- + h->dst.pix_fmt = convert_csp_to_pix_fmt( h->dst_csp );
- + h->scale = h->dst;
- + int src_pix_fmt = convert_csp_to_pix_fmt( info->csp );
- + /* confirm swscale can support this conversion */
- + if( !sws_isSupportedInput( src_pix_fmt ) )
- + {
- + fprintf( stderr, "resize [error]: input colorspace %s is not supported\n", sws_format_name( src_pix_fmt ) );
- + return -1;
- + }
- + if( !sws_isSupportedOutput( h->dst.pix_fmt ) )
- + {
- + fprintf( stderr, "resize [error]: output colorspace %s is not supported\n", sws_format_name( h->dst.pix_fmt ) );
- + return -1;
- + }
- +
- + if( h->dst.width != info->width || h->dst.height != info->height )
- + fprintf( stderr, "resize [info]: resizing to %dx%d\n", h->dst.width, h->dst.height );
- + if( h->dst.pix_fmt != src_pix_fmt )
- + fprintf( stderr, "resize [warning]: converting from %s to %s\n", sws_format_name( src_pix_fmt ),
- + sws_format_name( h->dst.pix_fmt ) );
- + h->dst_csp |= info->csp & X264_CSP_VFLIP; // preserve vflip
- + /* finished initing, overwrite values */
- + info->csp = h->dst_csp;
- + info->width = h->dst.width;
- + info->height = h->dst.height;
- +
- + h->prev_filter = *filter;
- + h->prev_hnd = *handle;
- + *handle = h;
- + *filter = resize_filter;
- +
- + return 0;
- +}
- +
- +static int check_resizer( resizer_hnd_t *h, cli_pic_t *in )
- +{
- + frame_prop_t input_prop = { in->img.width, in->img.height, convert_csp_to_pix_fmt( in->img.csp ) };
- + if( !memcmp( &input_prop, &h->scale, sizeof(frame_prop_t) ) )
- + return 0;
- + if( h->ctx )
- + {
- + sws_freeContext( h->ctx );
- + fprintf( stderr, "resize [warning]: stream properties changed at pts %"PRId64"\n", in->pts );
- + }
- + h->scale = input_prop;
- + if( !h->buffer_allocated )
- + {
- + if( x264_cli_pic_alloc( &h->buffer, h->dst_csp, h->dst.width, h->dst.height ) )
- + return -1;
- + h->buffer_allocated = 1;
- + }
- + h->ctx = sws_getContext( h->scale.width, h->scale.height, h->scale.pix_fmt, h->dst.width,
- + h->dst.height, h->dst.pix_fmt, h->ctx_flags, NULL, NULL, NULL );
- + if( !h->ctx )
- + {
- + fprintf( stderr, "resize [error]: swscale init failed\n" );
- + return -1;
- + }
- + return 0;
- +}
- +
- +static int get_frame( hnd_t handle, cli_pic_t *output, int frame )
- +{
- + resizer_hnd_t *h = handle;
- + cli_pic_t in;
- + if( h->prev_filter.get_frame( h->prev_hnd, &in, frame ) )
- + return -1;
- + if( check_resizer( h, &in ) )
- + return -1;
- + *output = in; /* copy all data */
- + if( h->ctx )
- + {
- + sws_scale( h->ctx, (const uint8_t* const*)in.img.plane, in.img.stride, 0,
- + in.img.height, h->buffer.img.plane, h->buffer.img.stride );
- + output->img = h->buffer.img; /* copy img data */
- + }
- + else
- + output->img.csp = h->dst_csp;
- +
- + return 0;
- +}
- +
- +static int release_frame( hnd_t handle, cli_pic_t *pic, int frame )
- +{
- + resizer_hnd_t *h = handle;
- + return h->prev_filter.release_frame( h->prev_hnd, pic, frame );
- +}
- +
- +static void free_filter( hnd_t handle )
- +{
- + resizer_hnd_t *h = handle;
- + h->prev_filter.free( h->prev_hnd );
- + if( h->ctx )
- + sws_freeContext( h->ctx );
- + if( h->buffer_allocated )
- + x264_cli_pic_clean( &h->buffer );
- + free( h );
- +}
- +
- +#else /* no swscale */
- +static int init( hnd_t *handle, cli_vid_filter_t *filter, video_info_t *info, x264_param_t *param, char *opt_string )
- +{
- + int ret = 0;
- +
- + if( !opt_string )
- + ret = full_check( info, param );
- + else
- + {
- + if( !strcmp( opt_string, "csp" ) )
- + ret = csp_check( info );
- + else if( !strcmp( opt_string, "normcsp" ) )
- + ret = info->csp & X264_CSP_OTHER;
- + else
- + ret = -1;
- + }
- +
- + /* pass if nothing needs to be done, otherwise fail */
- + if( ret )
- + fprintf( stderr, "x264 [error]: resizer filter failed, not compiled with swscale support\n" );
- + return ret;
- +}
- +
- +#define help NULL
- +#define get_frame NULL
- +#define release_frame NULL
- +#define free_filter NULL
- +#define convert_csp_to_pix_fmt(x) (x & X264_CSP_MASK)
- +
- +#endif
- +
- +static int csp_check( video_info_t *info )
- +{
- + return convert_csp_to_pix_fmt( info->csp ) != convert_csp_to_pix_fmt( info->dst_csp );
- +}
- +
- +cli_vid_filter_t resize_filter = { "resize", help, init, get_frame, release_frame, free_filter, NULL };
- Index: filter/select_every.c
- ===================================================================
- --- /dev/null
- +++ filter/select_every.c
- @@ -0,0 +1,161 @@
- +/*****************************************************************************
- + * select_every.c: x264 select every filter
- + *****************************************************************************
- + * Copyright (C) 2010 Steven Walters <kemuri9@gmail.com>
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License as published by
- + * the Free Software Foundation; either version 2 of the License, or
- + * (at your option) any later version.
- + *
- + * This program 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 General Public License for more details.
- + *
- + * You should have received a copy of the GNU General Public License
- + * along with this program; if not, write to the Free Software
- + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111, USA.
- + *****************************************************************************/
- +
- +#include "filter.h"
- +
- +#define MAX_PATTERN_SIZE 100 /* arbitrary */
- +
- +typedef struct
- +{
- + hnd_t prev_hnd;
- + cli_vid_filter_t prev_filter;
- +
- + int *pattern;
- + int pattern_len;
- + int step_size;
- + int vfr;
- + int64_t pts;
- +} selvry_hnd_t;
- +
- +cli_vid_filter_t select_every_filter;
- +
- +static void help( int longhelp )
- +{
- + printf( " select_every:step,offset1[,...]\n" );
- + if( !longhelp )
- + return;
- + printf( " apply a selection pattern to input frames\n"
- + " see: http://avisynth.org/mediawiki/Select#SelectEvery\n" );
- +}
- +
- +static int init( hnd_t *handle, cli_vid_filter_t *filter, video_info_t *info, x264_param_t *param, char *opt_string )
- +{
- + selvry_hnd_t *h = malloc( sizeof(selvry_hnd_t) );
- + if( !h )
- + return -1;
- + h->pattern_len = 0;
- + h->step_size = 0;
- + int offsets[MAX_PATTERN_SIZE];
- + for( char *tok, *p = opt_string; (tok = strtok( p, "," )); p = NULL )
- + {
- + int val = atoi( tok );
- + if( p )
- + {
- + h->step_size = val;
- + continue;
- + }
- + if( val < 0 || val >= h->step_size || (!val && strcmp( tok, "0" )) )
- + {
- + fprintf( stderr, "select_every [error]: invalid offset `%s'\n", tok );
- + return -1;
- + }
- + else if( h->pattern_len >= MAX_PATTERN_SIZE )
- + {
- + fprintf( stderr, "select_every [error]: max pattern size %d reached\n", MAX_PATTERN_SIZE );
- + return -1;
- + }
- + offsets[h->pattern_len++] = val;
- + }
- + if( h->step_size <= 0 )
- + {
- + fprintf( stderr, "select_every [error]: no or invalid step size provided\n" );
- + return -1;
- + }
- + if( !h->pattern_len )
- + {
- + fprintf( stderr, "select_every [error]: no offsets supplied\n" );
- + return -1;
- + }
- +
- + h->pattern = malloc( h->pattern_len * sizeof(int) );
- + if( !h->pattern )
- + return -1;
- + memcpy( h->pattern, offsets, h->pattern_len * sizeof(int) );
- +
- + /* determine required cache size to maintain pattern. */
- + intptr_t max_rewind = 0;
- + int min = h->step_size;
- + for( int i = h->pattern_len-1; i >= 0; i-- )
- + {
- + min = X264_MIN( min, offsets[i] );
- + if( i )
- + max_rewind = X264_MAX( max_rewind, offsets[i-1] - min + 1 );
- + /* reached maximum rewind size */
- + if( max_rewind == h->step_size )
- + break;
- + }
- + if( x264_init_vid_filter( "cache", handle, filter, info, param, (void*)max_rewind ) )
- + return -1;
- +
- + /* done initing, overwrite properties */
- + if( h->step_size != h->pattern_len )
- + {
- + info->num_frames = (uint64_t)info->num_frames * h->pattern_len / h->step_size;
- + info->fps_den *= h->step_size;
- + info->fps_num *= h->pattern_len;
- + x264_reduce_fraction( &info->fps_num, &info->fps_den );
- + if( info->vfr )
- + {
- + info->timebase_den *= h->pattern_len;
- + info->timebase_num *= h->step_size;
- + x264_reduce_fraction( &info->timebase_num, &info->timebase_den );
- + }
- + }
- +
- + h->pts = 0;
- + h->vfr = info->vfr;
- + h->prev_filter = *filter;
- + h->prev_hnd = *handle;
- + *filter = select_every_filter;
- + *handle = h;
- +
- + return 0;
- +}
- +
- +static int get_frame( hnd_t handle, cli_pic_t *output, int frame )
- +{
- + selvry_hnd_t *h = handle;
- + int pat_frame = h->pattern[frame % h->pattern_len] + frame / h->pattern_len * h->step_size;
- + if( h->prev_filter.get_frame( h->prev_hnd, output, pat_frame ) )
- + return -1;
- + if( h->vfr )
- + {
- + output->pts = h->pts;
- + h->pts += output->duration;
- + }
- + return 0;
- +}
- +
- +static int release_frame( hnd_t handle, cli_pic_t *pic, int frame )
- +{
- + selvry_hnd_t *h = handle;
- + int pat_frame = h->pattern[frame % h->pattern_len] + frame / h->pattern_len * h->step_size;
- + return h->prev_filter.release_frame( h->prev_hnd, pic, pat_frame );
- +}
- +
- +static void free_filter( hnd_t handle )
- +{
- + selvry_hnd_t *h = handle;
- + h->prev_filter.free( h->prev_hnd );
- + free( h->pattern );
- + free( h );
- +}
- +
- +cli_vid_filter_t select_every_filter = { "select_every", help, init, get_frame, release_frame, free_filter, NULL };
- Index: filter/source.c
- ===================================================================
- --- /dev/null
- +++ filter/source.c
- @@ -0,0 +1,76 @@
- +/*****************************************************************************
- + * source.c: x264 source filter
- + *****************************************************************************
- + * Copyright (C) 2010 Steven Walters <kemuri9@gmail.com>
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License as published by
- + * the Free Software Foundation; either version 2 of the License, or
- + * (at your option) any later version.
- + *
- + * This program 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 General Public License for more details.
- + *
- + * You should have received a copy of the GNU General Public License
- + * along with this program; if not, write to the Free Software
- + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111, USA.
- + *****************************************************************************/
- +
- +#include "filter.h"
- +
- +typedef struct
- +{
- + cli_pic_t pic;
- + hnd_t hin;
- + int cur_frame;
- +} source_hnd_t;
- +
- +cli_vid_filter_t source_filter;
- +
- +static int init( hnd_t *handle, cli_vid_filter_t *filter, video_info_t *info, x264_param_t *param, char *opt_string )
- +{
- + source_hnd_t *h = calloc( 1, sizeof(source_hnd_t) );
- + if( !h )
- + return -1;
- + h->cur_frame = -1;
- +
- + if( input.picture_alloc( &h->pic, info->csp, info->width, info->height ) )
- + return -1;
- +
- + h->hin = *handle;
- + *handle = h;
- + *filter = source_filter;
- +
- + return 0;
- +}
- +
- +static int get_frame( hnd_t handle, cli_pic_t *output, int frame )
- +{
- + source_hnd_t *h = handle;
- + /* do not allow requesting of frames from before the current position */
- + if( frame <= h->cur_frame || input.read_frame( &h->pic, h->hin, frame ) )
- + return -1;
- + h->cur_frame = frame;
- + *output = h->pic;
- + return 0;
- +}
- +
- +static int release_frame( hnd_t handle, cli_pic_t *pic, int frame )
- +{
- + source_hnd_t *h = handle;
- + if( input.release_frame && input.release_frame( &h->pic, h->hin ) )
- + return -1;
- + return 0;
- +}
- +
- +static void free_filter( hnd_t handle )
- +{
- + source_hnd_t *h = handle;
- + input.picture_clean( &h->pic );
- + input.close_file( h->hin );
- + free( h );
- +}
- +
- +cli_vid_filter_t source_filter = { "source", NULL, init, get_frame, release_frame, free_filter, NULL };
- Index: filter/utils.c
- ===================================================================
- --- /dev/null
- +++ filter/utils.c
- @@ -0,0 +1,50 @@
- +/*****************************************************************************
- + * utils.c: x264 filter utilities
- + *****************************************************************************
- + * Copyright (C) 2010 Steven Walters <kemuri9@gmail.com>
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License as published by
- + * the Free Software Foundation; either version 2 of the License, or
- + * (at your option) any later version.
- + *
- + * This program 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 General Public License for more details.
- + *
- + * You should have received a copy of the GNU General Public License
- + * along with this program; if not, write to the Free Software
- + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111, USA.
- + *****************************************************************************/
- +
- +#include "utils.h"
- +
- +int x264_cli_pic_copy( cli_pic_t *out, cli_pic_t *in )
- +{
- + int csp = in->img.csp & X264_CSP_MASK;
- + if( csp >= X264_CSP_CLI_MAX || csp <= X264_CSP_NONE || in->img.csp & X264_CSP_OTHER )
- + {
- + fprintf( stderr, "x264 [error]: invalid colorspace arg\n" );
- + return -1;
- + }
- + if( in->img.csp != out->img.csp || in->img.height != out->img.height ||
- + in->img.width != out->img.width )
- + {
- + fprintf( stderr, "x264 [error]: incompatible frame properties\n" );
- + return -1;
- + }
- + /* copy data */
- + out->duration = in->duration;
- + out->pts = in->pts;
- + out->opaque = in->opaque;
- +
- + for( int i = 0; i < out->img.planes; i++ )
- + {
- + int height = in->img.height * x264_cli_csps[csp].height[i];
- + int width = in->img.width * x264_cli_csps[csp].width[i];
- + x264_plane_copy_c( out->img.plane[i], out->img.stride[i], in->img.plane[i],
- + in->img.stride[i], width, height );
- + }
- + return 0;
- +}
- Index: filter/utils.h
- ===================================================================
- --- /dev/null
- +++ filter/utils.h
- @@ -0,0 +1,24 @@
- +/*****************************************************************************
- + * utils.h: x264 filter utilities
- + *****************************************************************************
- + * Copyright (C) 2010 Steven Walters <kemuri9@gmail.com>
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License as published by
- + * the Free Software Foundation; either version 2 of the License, or
- + * (at your option) any later version.
- + *
- + * This program 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 General Public License for more details.
- + *
- + * You should have received a copy of the GNU General Public License
- + * along with this program; if not, write to the Free Software
- + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111, USA.
- + *****************************************************************************/
- +
- +#include "filter.h"
- +
- +void x264_plane_copy_c( uint8_t *dst, int i_dst, uint8_t *src, int i_src, int w, int h );
- +int x264_cli_pic_copy( cli_pic_t *out, cli_pic_t *in );
- Index: input/avs.c
- ===================================================================
- --- input/avs_orig.c
- +++ input/avs.c
- @@ -42,6 +42,10 @@
- /* when AVS supports other planar colorspaces, a workaround is required */
- #define AVS_INTERFACE_OTHER_PLANAR 5
- +#ifdef HAVE_SWSCALE
- +#include <libavutil/pixfmt.h>
- +#endif
- +
- /* maximum size of the sequence of filters to try on non script files */
- #define AVS_MAX_SEQUENCE 5
- @@ -236,17 +240,23 @@
- info->interlaced = 1;
- info->tff = avs_is_tff( vi );
- }
- - if( vi->width&1 || vi->height&1 )
- - {
- - fprintf( stderr, "avs [error]: input clip width or height not divisible by 2 (%dx%d)\n",
- - vi->width, vi->height );
- - return -1;
- - }
- + /* if swscale is available, convert CSPs with it rather than with avisynth. */
- +#ifdef HAVE_SWSCALE
- + int convert_to_yv12 = 0;
- +#else
- + int convert_to_yv12 = !avs_is_yv12( vi );
- +#endif
- /* always call ConvertToYV12 to convert non YV12 planar colorspaces to YV12 when user's AVS supports them,
- as all planar colorspaces are flagged as YV12. If it is already YV12 in this case, the call does nothing */
- - if( !avs_is_yv12( vi ) || avs_version >= AVS_INTERFACE_OTHER_PLANAR )
- + if( convert_to_yv12 || (avs_version >= AVS_INTERFACE_OTHER_PLANAR && avs_is_yv12( vi )) )
- {
- - fprintf( stderr, "avs %s\n", !avs_is_yv12( vi ) ? "[warning]: converting input clip to YV12"
- + if( vi->width&1 || vi->height&1 )
- + {
- + fprintf( stderr, "avs [error]: input clip width or height not divisible by 2 (%dx%d)\n",
- + vi->width, vi->height );
- + return -1;
- + }
- + fprintf( stderr, "avs %s\n", convert_to_yv12 ? "[warning]: converting input clip to YV12"
- : "[info]: avisynth 2.6+ detected, forcing conversion to YV12" );
- const char *arg_name[2] = { NULL, "interlaced" };
- AVS_Value arg_arr[2] = { res, avs_new_value_bool( info->interlaced ) };
- @@ -260,65 +270,69 @@
- }
- h->func.avs_release_value( res );
- - info->width = vi->width;
- - info->height = vi->height;
- + info->width = vi->width;
- + info->height = vi->height;
- info->fps_num = vi->fps_numerator;
- info->fps_den = vi->fps_denominator;
- - h->num_frames = vi->num_frames;
- - info->csp = X264_CSP_YV12;
- + h->num_frames = info->num_frames = vi->num_frames;
- + info->thread_safe = 1;
- +#ifdef HAVE_SWSCALE
- + if( avs_is_rgb32( vi ) )
- + info->csp = X264_CSP_BGRA | X264_CSP_VFLIP;
- + else if( avs_is_rgb24( vi ) )
- + info->csp = X264_CSP_BGR | X264_CSP_VFLIP;
- + else if( avs_is_yuy2( vi ) )
- + info->csp = PIX_FMT_YUYV422 | X264_CSP_OTHER;
- + else /* yv12 */
- + info->csp = X264_CSP_I420;
- +#endif
- info->vfr = 0;
- *p_handle = h;
- return 0;
- }
- -static int get_frame_total( hnd_t handle )
- -{
- - avs_hnd_t *h = handle;
- - return h->num_frames;
- -}
- -
- -static int picture_alloc( x264_picture_t *pic, int i_csp, int i_width, int i_height )
- +static int picture_alloc( cli_pic_t *pic, int csp, int width, int height )
- {
- - pic->img.i_csp = i_csp;
- - pic->img.i_plane = 3;
- - pic->param = NULL;
- - pic->i_pic_struct = PIC_STRUCT_AUTO;
- + if( x264_cli_pic_alloc( pic, X264_CSP_NONE, width, height ) )
- + return -1;
- + pic->img.csp = csp;
- + pic->img.planes = (csp & X264_CSP_OTHER) ? 1 : x264_cli_csps[csp & X264_CSP_MASK].planes;
- return 0;
- }
- -static int read_frame( x264_picture_t *p_pic, hnd_t handle, int i_frame )
- +static int read_frame( cli_pic_t *pic, hnd_t handle, int i_frame )
- {
- - static int plane[3] = { AVS_PLANAR_Y, AVS_PLANAR_V, AVS_PLANAR_U };
- + static int plane[3] = { AVS_PLANAR_Y, AVS_PLANAR_U, AVS_PLANAR_V };
- avs_hnd_t *h = handle;
- if( i_frame >= h->num_frames )
- return -1;
- - AVS_VideoFrame *frm = p_pic->opaque = h->func.avs_get_frame( h->clip, i_frame );
- + AVS_VideoFrame *frm = pic->opaque = h->func.avs_get_frame( h->clip, i_frame );
- const char *err = h->func.avs_clip_get_error( h->clip );
- if( err )
- {
- fprintf( stderr, "avs [error]: %s occurred while reading frame %d\n", err, i_frame );
- return -1;
- }
- - for( int i = 0; i < 3; i++ )
- + for( int i = 0; i < pic->img.planes; i++ )
- {
- /* explicitly cast away the const attribute to avoid a warning */
- - p_pic->img.plane[i] = (uint8_t*)avs_get_read_ptr_p( frm, plane[i] );
- - p_pic->img.i_stride[i] = avs_get_pitch_p( frm, plane[i] );
- + pic->img.plane[i] = (uint8_t*)avs_get_read_ptr_p( frm, plane[i] );
- + pic->img.stride[i] = avs_get_pitch_p( frm, plane[i] );
- }
- return 0;
- }
- -static int release_frame( x264_picture_t *pic, hnd_t handle )
- +static int release_frame( cli_pic_t *pic, hnd_t handle )
- {
- avs_hnd_t *h = handle;
- h->func.avs_release_video_frame( pic->opaque );
- return 0;
- }
- -static void picture_clean( x264_picture_t *pic )
- +static void picture_clean( cli_pic_t *pic )
- {
- - memset( pic, 0, sizeof(x264_picture_t) );
- + memset( pic, 0, sizeof(cli_pic_t) );
- }
- static int close_file( hnd_t handle )
- @@ -332,4 +346,4 @@
- return 0;
- }
- -const cli_input_t avs_input = { open_file, get_frame_total, picture_alloc, read_frame, release_frame, picture_clean, close_file };
- +const cli_input_t avs_input = { open_file, picture_alloc, read_frame, release_frame, picture_clean, close_file };
- Index: input/common.c
- ===================================================================
- --- /dev/null
- +++ input/common.c
- @@ -0,0 +1,86 @@
- +/*****************************************************************************
- + * common.c: x264 input module common
- + *****************************************************************************
- + * Copyright (C) 2010 Steven Walters <kemuri9@gmail.com>
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License as published by
- + * the Free Software Foundation; either version 2 of the License, or
- + * (at your option) any later version.
- + *
- + * This program 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 General Public License for more details.
- + *
- + * You should have received a copy of the GNU General Public License
- + * along with this program; if not, write to the Free Software
- + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111, USA.
- + *****************************************************************************/
- +
- +#include "input.h"
- +
- +const x264_cli_csp_t x264_cli_csps[] = {
- + [X264_CSP_I420] = { "i420", 3, { 1, .5, .5 }, { 1, .5, .5 } },
- + [X264_CSP_I422] = { "i422", 3, { 1, .5, .5 }, { 1, 1, 1 } },
- + [X264_CSP_I444] = { "i444", 3, { 1, 1, 1 }, { 1, 1, 1 } },
- + [X264_CSP_YV12] = { "yv12", 3, { 1, .5, .5 }, { 1, .5, .5 } },
- + [X264_CSP_BGR] = { "bgr", 1, { 3 }, { 1 }, },
- + [X264_CSP_BGRA] = { "bgra", 1, { 4 }, { 1 }, }
- +};
- +
- +static int is_invalid_csp( int csp )
- +{
- + int csp_mask = csp & X264_CSP_MASK;
- + return csp_mask <= X264_CSP_NONE || csp_mask >= X264_CSP_CLI_MAX || csp & X264_CSP_OTHER;
- +}
- +
- +uint64_t x264_cli_pic_plane_size( int csp, int width, int height, int plane )
- +{
- + int csp_mask = csp & X264_CSP_MASK;
- + if( is_invalid_csp( csp ) || plane < 0 || plane >= x264_cli_csps[csp_mask].planes )
- + return 0;
- + uint64_t size = (uint64_t)width * height;
- + size *= x264_cli_csps[csp_mask].width[plane] * x264_cli_csps[csp_mask].height[plane];
- + return size;
- +}
- +
- +uint64_t x264_cli_pic_size( int csp, int width, int height )
- +{
- + if( is_invalid_csp( csp ) )
- + return 0;
- + uint64_t size = 0;
- + int csp_mask = csp & X264_CSP_MASK;
- + for( int i = 0; i < x264_cli_csps[csp_mask].planes; i++ )
- + size += x264_cli_pic_plane_size( csp, width, height, i );
- + return size;
- +}
- +
- +int x264_cli_pic_alloc( cli_pic_t *pic, int csp, int width, int height )
- +{
- + memset( pic, 0, sizeof(cli_pic_t) );
- + int csp_mask = csp & X264_CSP_MASK;
- + if( is_invalid_csp( csp ) )
- + pic->img.planes = 0;
- + else
- + pic->img.planes = x264_cli_csps[csp_mask].planes;
- + pic->img.csp = csp;
- + pic->img.width = width;
- + pic->img.height = height;
- + for( int i = 0; i < pic->img.planes; i++ )
- + {
- + pic->img.plane[i] = x264_malloc( x264_cli_pic_plane_size( csp, width, height, i ) );
- + if( !pic->img.plane[i] )
- + return -1;
- + pic->img.stride[i] = width * x264_cli_csps[csp_mask].width[i];
- + }
- +
- + return 0;
- +}
- +
- +void x264_cli_pic_clean( cli_pic_t *pic )
- +{
- + for( int i = 0; i < pic->img.planes; i++ )
- + x264_free( pic->img.plane[i] );
- + memset( pic, 0, sizeof(cli_pic_t) );
- +}
- Index: input/ffms.c
- ===================================================================
- --- input/ffms_orig.c
- +++ input/ffms.c
- @@ -37,19 +37,8 @@
- {
- FFMS_VideoSource *video_source;
- FFMS_Track *track;
- - int total_frames;
- - struct SwsContext *scaler;
- - int pts_offset_flag;
- - int64_t pts_offset;
- int reduce_pts;
- int vfr_input;
- -
- - int init_width;
- - int init_height;
- -
- - int cur_width;
- - int cur_height;
- - int cur_pix_fmt;
- } ffms_hnd_t;
- static int FFMS_CC update_progress( int64_t current, int64_t total, void *private )
- @@ -113,12 +102,14 @@
- FFMS_DestroyIndex( index );
- const FFMS_VideoProperties *videop = FFMS_GetVideoProperties( h->video_source );
- - h->total_frames = videop->NumFrames;
- + info->num_frames = videop->NumFrames;
- info->sar_height = videop->SARDen;
- info->sar_width = videop->SARNum;
- info->fps_den = videop->FPSDenominator;
- info->fps_num = videop->FPSNumerator;
- h->vfr_input = info->vfr;
- + /* ffms is thread unsafe as it uses a single frame buffer for all frame requests */
- + info->thread_safe = 0;
- const FFMS_Frame *frame = FFMS_GetFrame( h->video_source, 0, &e );
- if( !frame )
- @@ -127,16 +118,12 @@
- return -1;
- }
- - h->init_width = h->cur_width = info->width = frame->EncodedWidth;
- - h->init_height = h->cur_height = info->height = frame->EncodedHeight;
- - h->cur_pix_fmt = frame->EncodedPixelFormat;
- + info->width = frame->EncodedWidth;
- + info->height = frame->EncodedHeight;
- + info->csp = frame->EncodedPixelFormat | X264_CSP_OTHER;
- info->interlaced = frame->InterlacedFrame;
- info->tff = frame->TopFieldFirst;
- - if( h->cur_pix_fmt != PIX_FMT_YUV420P )
- - fprintf( stderr, "ffms [warning]: converting from %s to YV12\n",
- - avcodec_get_pix_fmt_name( h->cur_pix_fmt ) );
- -
- /* ffms timestamps are in milliseconds. ffms also uses int64_ts for timebase,
- * so we need to reduce large timebases to prevent overflow */
- if( h->vfr_input )
- @@ -160,60 +147,29 @@
- return 0;
- }
- -static int get_frame_total( hnd_t handle )
- -{
- - return ((ffms_hnd_t*)handle)->total_frames;
- -}
- -
- -static int check_swscale( ffms_hnd_t *h, const FFMS_Frame *frame, int i_frame )
- +static int picture_alloc( cli_pic_t *pic, int csp, int width, int height )
- {
- - if( h->scaler && h->cur_width == frame->EncodedWidth && h->cur_height == frame->EncodedHeight &&
- - h->cur_pix_fmt == frame->EncodedPixelFormat )
- - return 0;
- - if( h->scaler )
- - {
- - sws_freeContext( h->scaler );
- - fprintf( stderr, "ffms [warning]: stream properties changed to %dx%d, %s at frame %d \n", frame->EncodedWidth,
- - frame->EncodedHeight, avcodec_get_pix_fmt_name( frame->EncodedPixelFormat ), i_frame );
- - h->cur_width = frame->EncodedWidth;
- - h->cur_height = frame->EncodedHeight;
- - h->cur_pix_fmt = frame->EncodedPixelFormat;
- - }
- - h->scaler = sws_getContext( h->cur_width, h->cur_height, h->cur_pix_fmt, h->init_width, h->init_height,
- - PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL );
- - if( !h->scaler )
- - {
- - fprintf( stderr, "ffms [error]: could not open swscale context\n" );
- + if( x264_cli_pic_alloc( pic, csp, width, height ) )
- return -1;
- - }
- + pic->img.planes = 4;
- return 0;
- }
- -static int read_frame( x264_picture_t *p_pic, hnd_t handle, int i_frame )
- +static int read_frame( cli_pic_t *pic, hnd_t handle, int i_frame )
- {
- ffms_hnd_t *h = handle;
- FFMS_ErrorInfo e;
- e.BufferSize = 0;
- const FFMS_Frame *frame = FFMS_GetFrame( h->video_source, i_frame, &e );
- if( !frame )
- - {
- - fprintf( stderr, "ffms [error]: could not read frame %d\n", i_frame );
- return -1;
- - }
- -
- - if( check_swscale( h, frame, i_frame ) )
- - return -1;
- - /* FFMS_VideoSource has a single FFMS_Frame buffer for all calls to GetFrame.
- - * With threaded input, copying the pointers would result in the data changing during encoding.
- - * FIXME: don't do redundant sws_scales for singlethreaded input, or fix FFMS to allow
- - * multiple FFMS_Frame buffers. */
- - sws_scale( h->scaler, (const uint8_t * const *)frame->Data, (int*)frame->Linesize, 0,
- - frame->EncodedHeight, p_pic->img.plane, p_pic->img.i_stride );
- -
- - const FFMS_FrameInfo *info = FFMS_GetFrameInfo( h->track, i_frame );
- +
- + memcpy( pic->img.stride, frame->Linesize, sizeof(pic->img.stride) );
- + memcpy( pic->img.plane, frame->Data, sizeof(pic->img.plane) );
- if( h->vfr_input )
- {
- + const FFMS_FrameInfo *info = FFMS_GetFrameInfo( h->track, i_frame );
- if( info->PTS == AV_NOPTS_VALUE )
- {
- fprintf( stderr, "ffms [error]: invalid timestamp. "
- @@ -221,24 +177,22 @@
- return -1;
- }
- - if( !h->pts_offset_flag )
- - {
- - h->pts_offset = info->PTS;
- - h->pts_offset_flag = 1;
- - }
- -
- - p_pic->i_pts = (info->PTS - h->pts_offset) >> h->reduce_pts;
- + pic->pts = info->PTS >> h->reduce_pts;
- }
- return 0;
- }
- +static void picture_clean( cli_pic_t *pic )
- +{
- + memset( pic, 0, sizeof(cli_pic_t) );
- +}
- +
- static int close_file( hnd_t handle )
- {
- ffms_hnd_t *h = handle;
- - sws_freeContext( h->scaler );
- FFMS_DestroyVideoSource( h->video_source );
- free( h );
- return 0;
- }
- -const cli_input_t ffms_input = { open_file, get_frame_total, x264_picture_alloc, read_frame, NULL, x264_picture_clean, close_file };
- +const cli_input_t ffms_input = { open_file, picture_alloc, read_frame, NULL, picture_clean, close_file };
- Index: input/input.h
- ===================================================================
- --- input/input_orig.h
- +++ input/input.h
- @@ -25,11 +25,14 @@
- #ifndef X264_INPUT_H
- #define X264_INPUT_H
- +#include "muxers.h"
- +
- /* options that are used by only some demuxers */
- typedef struct
- {
- char *index;
- - char *resolution; /* resolution string parsed by raw yuv input */
- + char *resolution;
- + char *colorspace;
- char *timebase;
- int seek;
- int demuxer_threads;
- @@ -38,37 +41,81 @@
- /* properties of the source given by the demuxer */
- typedef struct
- {
- - int csp; /* X264_CSP_YV12 or X264_CSP_I420 */
- + int csp; /* actual colorspace */
- + int dst_csp; /* colorspace demuxer says to give to libx264 */
- uint32_t fps_num;
- uint32_t fps_den;
- int height;
- int interlaced;
- + int num_frames;
- uint32_t sar_width;
- uint32_t sar_height;
- int tff;
- + int thread_safe; /* demuxer is thread_input safe */
- uint32_t timebase_num;
- uint32_t timebase_den;
- int vfr;
- int width;
- } video_info_t;
- +/* image data type used by demuxers */
- +typedef struct
- +{
- + int csp; /* colorspace */
- + int width; /* width of the picture */
- + int height; /* height of the picture */
- + int planes; /* number of planes */
- + uint8_t *plane[4]; /* pointers for each plane */
- + int stride[4]; /* strides for each plane */
- +} cli_image_t;
- +
- +typedef struct
- +{
- + cli_image_t img;
- + int64_t pts; /* input pts */
- + int64_t duration; /* frame duration - used for vfr */
- + void *opaque; /* opaque handle */
- +} cli_pic_t;
- +
- typedef struct
- {
- int (*open_file)( char *psz_filename, hnd_t *p_handle, video_info_t *info, cli_input_opt_t *opt );
- - int (*get_frame_total)( hnd_t handle );
- - int (*picture_alloc)( x264_picture_t *pic, int i_csp, int i_width, int i_height );
- - int (*read_frame)( x264_picture_t *p_pic, hnd_t handle, int i_frame );
- - int (*release_frame)( x264_picture_t *pic, hnd_t handle );
- - void (*picture_clean)( x264_picture_t *pic );
- + int (*picture_alloc)( cli_pic_t *pic, int csp, int width, int height );
- + int (*read_frame)( cli_pic_t *pic, hnd_t handle, int i_frame );
- + int (*release_frame)( cli_pic_t *pic, hnd_t handle );
- + void (*picture_clean)( cli_pic_t *pic );
- int (*close_file)( hnd_t handle );
- } cli_input_t;
- -extern const cli_input_t yuv_input;
- +extern const cli_input_t raw_input;
- extern const cli_input_t y4m_input;
- extern const cli_input_t avs_input;
- extern cli_input_t thread_input;
- extern const cli_input_t lavf_input;
- extern const cli_input_t ffms_input;
- extern cli_input_t timecode_input;
- +
- +extern cli_input_t input;
- +
- +/* extended colorspace list that isn't recognized by libx264 but by the cli */
- +#define X264_CSP_BGR X264_CSP_MAX /* packed bgr 24bits */
- +#define X264_CSP_BGRA (X264_CSP_MAX+1) /* packed bgr 32bits */
- +#define X264_CSP_CLI_MAX (X264_CSP_MAX+2) /* end of list */
- +#define X264_CSP_OTHER 0x2000 /* non x264 colorspace */
- +
- +typedef struct
- +{
- + const char *name;
- + int planes;
- + float width[4];
- + float height[4];
- +} x264_cli_csp_t;
- +
- +extern const x264_cli_csp_t x264_cli_csps[];
- +
- +int x264_cli_pic_alloc( cli_pic_t *pic, int csp, int width, int height );
- +void x264_cli_pic_clean( cli_pic_t *pic );
- +uint64_t x264_cli_pic_plane_size( int csp, int width, int height, int plane );
- +uint64_t x264_cli_pic_size( int csp, int width, int height );
- #endif
- Index: input/lavf.c
- ===================================================================
- --- input/lavf_orig.c
- +++ input/lavf.c
- @@ -24,58 +24,21 @@
- #include "muxers.h"
- #undef DECLARE_ALIGNED
- #include <libavformat/avformat.h>
- -#include <libswscale/swscale.h>
- +
- +/* located in libavutil/pixdesc.h */
- +enum PixelFormat av_get_pix_fmt( const char *name );
- typedef struct
- {
- AVFormatContext *lavf;
- + AVFormatParameters *param;
- int stream_id;
- int next_frame;
- int vfr_input;
- - int vertical_flip;
- - struct SwsContext *scaler;
- - int pts_offset_flag;
- - int64_t pts_offset;
- - x264_picture_t *first_pic;
- -
- - int init_width;
- - int init_height;
- -
- - int cur_width;
- - int cur_height;
- - enum PixelFormat cur_pix_fmt;
- + cli_pic_t *first_pic;
- } lavf_hnd_t;
- -typedef struct
- -{
- - AVFrame frame;
- - AVPacket packet;
- -} lavf_pic_t;
- -
- -static int check_swscale( lavf_hnd_t *h, AVCodecContext *c, int i_frame )
- -{
- - if( h->scaler && (h->cur_width == c->width) && (h->cur_height == c->height) && (h->cur_pix_fmt == c->pix_fmt) )
- - return 0;
- - if( h->scaler )
- - {
- - sws_freeContext( h->scaler );
- - fprintf( stderr, "lavf [warning]: stream properties changed to %dx%d, %s at frame %d \n",
- - c->width, c->height, avcodec_get_pix_fmt_name( c->pix_fmt ), i_frame );
- - h->cur_width = c->width;
- - h->cur_height = c->height;
- - h->cur_pix_fmt = c->pix_fmt;
- - }
- - h->scaler = sws_getContext( h->cur_width, h->cur_height, h->cur_pix_fmt, h->init_width, h->init_height,
- - PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL );
- - if( !h->scaler )
- - {
- - fprintf( stderr, "lavf [error]: could not open swscale context\n" );
- - return -1;
- - }
- - return 0;
- -}
- -
- -static int read_frame_internal( x264_picture_t *p_pic, lavf_hnd_t *h, int i_frame, video_info_t *info )
- +static int read_frame_internal( cli_pic_t *p_pic, lavf_hnd_t *h, int i_frame, video_info_t *info )
- {
- if( h->first_pic && !info )
- {
- @@ -83,9 +46,11 @@
- * if so, retrieve the pts and image data before freeing it. */
- if( !i_frame )
- {
- - XCHG( x264_image_t, p_pic->img, h->first_pic->img );
- - p_pic->i_pts = h->first_pic->i_pts;
- + XCHG( cli_image_t, p_pic->img, h->first_pic->img );
- + p_pic->pts = h->first_pic->pts;
- + XCHG( void*, p_pic->opaque, h->first_pic->opaque );
- }
- + lavf_input.release_frame( h->first_pic, NULL );
- lavf_input.picture_clean( h->first_pic );
- free( h->first_pic );
- h->first_pic = NULL;
- @@ -94,9 +59,9 @@
- }
- AVCodecContext *c = h->lavf->streams[h->stream_id]->codec;
- - lavf_pic_t *pic_h = p_pic->opaque;
- - AVPacket *pkt = &pic_h->packet;
- - AVFrame *frame = &pic_h->frame;
- + AVPacket *pkt = p_pic->opaque;
- + AVFrame frame;
- + avcodec_get_frame_defaults( &frame );
- while( i_frame >= h->next_frame )
- {
- @@ -105,12 +70,12 @@
- if( pkt->stream_index == h->stream_id )
- {
- c->reordered_opaque = pkt->pts;
- - if( avcodec_decode_video2( c, frame, &finished, pkt ) < 0 )
- + if( avcodec_decode_video2( c, &frame, &finished, pkt ) < 0 )
- fprintf( stderr, "lavf [warning]: video decoding failed on frame %d\n", h->next_frame );
- }
- if( !finished )
- {
- - if( avcodec_decode_video2( c, frame, &finished, pkt ) < 0 )
- + if( avcodec_decode_video2( c, &frame, &finished, pkt ) < 0 )
- fprintf( stderr, "lavf [warning]: video decoding failed on frame %d\n", h->next_frame );
- if( !finished )
- return -1;
- @@ -118,55 +83,57 @@
- h->next_frame++;
- }
- - if( check_swscale( h, c, i_frame ) )
- - return -1;
- - /* FIXME: avoid sws_scale where possible (no colorspace conversion). */
- - sws_scale( h->scaler, (const uint8_t * const *)frame->data, frame->linesize, 0, c->height, p_pic->img.plane, p_pic->img.i_stride );
- + memcpy( p_pic->img.stride, frame.linesize, sizeof(p_pic->img.stride) );
- + memcpy( p_pic->img.plane, frame.data, sizeof(p_pic->img.plane) );
- + p_pic->img.height = c->height;
- + p_pic->img.csp = c->pix_fmt | X264_CSP_OTHER;
- + p_pic->img.width = c->width;
- if( info )
- {
- - info->interlaced = frame->interlaced_frame;
- - info->tff = frame->top_field_first;
- + info->interlaced = frame.interlaced_frame;
- + info->tff = frame.top_field_first;
- }
- if( h->vfr_input )
- {
- - p_pic->i_pts = 0;
- - if( frame->reordered_opaque != AV_NOPTS_VALUE )
- - p_pic->i_pts = frame->reordered_opaque;
- + p_pic->pts = 0;
- + if( frame.reordered_opaque != AV_NOPTS_VALUE )
- + p_pic->pts = frame.reordered_opaque;
- else if( pkt->dts != AV_NOPTS_VALUE )
- - p_pic->i_pts = pkt->dts; // for AVI files
- + p_pic->pts = pkt->dts; // for AVI files
- else if( info )
- {
- h->vfr_input = info->vfr = 0;
- - goto exit;
- - }
- - if( !h->pts_offset_flag )
- - {
- - h->pts_offset = p_pic->i_pts;
- - h->pts_offset_flag = 1;
- + return 0;
- }
- - p_pic->i_pts -= h->pts_offset;
- }
- -exit:
- - if( pkt->destruct )
- - pkt->destruct( pkt );
- - avcodec_get_frame_defaults( frame );
- return 0;
- }
- static int open_file( char *psz_filename, hnd_t *p_handle, video_info_t *info, cli_input_opt_t *opt )
- {
- - lavf_hnd_t *h = malloc( sizeof(lavf_hnd_t) );
- + lavf_hnd_t *h = calloc( 1, sizeof(lavf_hnd_t) );
- if( !h )
- return -1;
- av_register_all();
- - h->scaler = NULL;
- if( !strcmp( psz_filename, "-" ) )
- psz_filename = "pipe:";
- - if( av_open_input_file( &h->lavf, psz_filename, NULL, 0, NULL ) )
- + AVInputFormat *fmt = NULL;
- + /* if resolution was passed in, assume rawvideo */
- + if( opt->resolution )
- + {
- + h->param = calloc( 1, sizeof(AVFormatParameters) );
- + if( !h->param )
- + return -1;
- + sscanf( opt->resolution, "%dx%d", &h->param->width, &h->param->height );
- + h->param->pix_fmt = opt->colorspace ? av_get_pix_fmt( opt->colorspace ) : PIX_FMT_YUV420P;
- + fmt = av_find_input_format( "rawvideo" );
- + }
- +
- + if( av_open_input_file( &h->lavf, psz_filename, fmt, 0, h->param ) )
- {
- fprintf( stderr, "lavf [error]: could not open input file\n" );
- return -1;
- @@ -188,27 +155,14 @@
- }
- h->stream_id = i;
- h->next_frame = 0;
- - h->pts_offset_flag = 0;
- - h->pts_offset = 0;
- AVCodecContext *c = h->lavf->streams[i]->codec;
- - h->init_width = h->cur_width = info->width = c->width;
- - h->init_height = h->cur_height = info->height = c->height;
- - h->cur_pix_fmt = c->pix_fmt;
- info->fps_num = h->lavf->streams[i]->r_frame_rate.num;
- info->fps_den = h->lavf->streams[i]->r_frame_rate.den;
- info->timebase_num = h->lavf->streams[i]->time_base.num;
- info->timebase_den = h->lavf->streams[i]->time_base.den;
- + /* lavf is thread unsafe as calling av_read_frame invalidates previously read AVPackets */
- + info->thread_safe = 0;
- h->vfr_input = info->vfr;
- - h->vertical_flip = 0;
- -
- - /* avisynth stores rgb data vertically flipped. */
- - if( !strcasecmp( get_filename_extension( psz_filename ), "avs" ) &&
- - (h->cur_pix_fmt == PIX_FMT_BGRA || h->cur_pix_fmt == PIX_FMT_BGR24) )
- - info->csp |= X264_CSP_VFLIP;
- -
- - if( h->cur_pix_fmt != PIX_FMT_YUV420P )
- - fprintf( stderr, "lavf [warning]: converting from %s to YV12\n",
- - avcodec_get_pix_fmt_name( h->cur_pix_fmt ) );
- if( opt->demuxer_threads > 1 )
- if( avcodec_thread_init( c, opt->demuxer_threads ) )
- @@ -221,8 +175,8 @@
- }
- /* prefetch the first frame and set/confirm flags */
- - h->first_pic = malloc( sizeof(x264_picture_t) );
- - if( !h->first_pic || lavf_input.picture_alloc( h->first_pic, info->csp, info->width, info->height ) )
- + h->first_pic = malloc( sizeof(cli_pic_t) );
- + if( !h->first_pic || lavf_input.picture_alloc( h->first_pic, X264_CSP_OTHER, info->width, info->height ) )
- {
- fprintf( stderr, "lavf [error]: malloc failed\n" );
- return -1;
- @@ -230,50 +184,62 @@
- else if( read_frame_internal( h->first_pic, h, 0, info ) )
- return -1;
- + info->width = c->width;
- + info->height = c->height;
- + info->csp = h->first_pic->img.csp;
- + info->num_frames = 0; /* FIXME */
- info->sar_height = c->sample_aspect_ratio.den;
- info->sar_width = c->sample_aspect_ratio.num;
- +
- + /* avisynth stores rgb data vertically flipped. */
- + if( !strcasecmp( get_filename_extension( psz_filename ), "avs" ) &&
- + (c->pix_fmt == PIX_FMT_BGRA || c->pix_fmt == PIX_FMT_BGR24) )
- + info->csp |= X264_CSP_VFLIP;
- +
- *p_handle = h;
- return 0;
- }
- -static int picture_alloc( x264_picture_t *pic, int i_csp, int i_width, int i_height )
- +static int picture_alloc( cli_pic_t *pic, int csp, int width, int height )
- {
- - if( x264_picture_alloc( pic, i_csp, i_width, i_height ) )
- + if( x264_cli_pic_alloc( pic, csp, width, height ) )
- return -1;
- - lavf_pic_t *pic_h = pic->opaque = malloc( sizeof(lavf_pic_t) );
- - if( !pic_h )
- + pic->img.planes = 4;
- + pic->opaque = malloc( sizeof(AVPacket) );
- + if( !pic->opaque )
- return -1;
- - avcodec_get_frame_defaults( &pic_h->frame );
- - av_init_packet( &pic_h->packet );
- + av_init_packet( pic->opaque );
- return 0;
- }
- -/* FIXME */
- -static int get_frame_total( hnd_t handle )
- +static int read_frame( cli_pic_t *pic, hnd_t handle, int i_frame )
- {
- - return 0;
- + return read_frame_internal( pic, handle, i_frame, NULL );
- }
- -static int read_frame( x264_picture_t *p_pic, hnd_t handle, int i_frame )
- +static int release_frame( cli_pic_t *pic, hnd_t handle )
- {
- - return read_frame_internal( p_pic, handle, i_frame, NULL );
- + av_free_packet( pic->opaque );
- + av_init_packet( pic->opaque );
- + return 0;
- }
- -static void picture_clean( x264_picture_t *pic )
- +static void picture_clean( cli_pic_t *pic )
- {
- free( pic->opaque );
- - x264_picture_clean( pic );
- + memset( pic, 0, sizeof(cli_pic_t) );
- }
- static int close_file( hnd_t handle )
- {
- lavf_hnd_t *h = handle;
- - sws_freeContext( h->scaler );
- avcodec_close( h->lavf->streams[h->stream_id]->codec );
- av_close_input_file( h->lavf );
- + if( h->param )
- + free( h->param );
- free( h );
- return 0;
- }
- -const cli_input_t lavf_input = { open_file, get_frame_total, picture_alloc, read_frame, NULL, picture_clean, close_file };
- +const cli_input_t lavf_input = { open_file, picture_alloc, read_frame, release_frame, picture_clean, close_file };
- Index: input/raw.c
- ===================================================================
- --- /dev/null
- +++ input/raw.c
- @@ -0,0 +1,136 @@
- +/*****************************************************************************
- + * raw.c: x264 raw input module
- + *****************************************************************************
- + * Copyright (C) 2003-2009 x264 project
- + *
- + * Authors: Laurent Aimar <fenrir@via.ecp.fr>
- + * Loren Merritt <lorenm@u.washington.edu>
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License as published by
- + * the Free Software Foundation; either version 2 of the License, or
- + * (at your option) any later version.
- + *
- + * This program 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 General Public License for more details.
- + *
- + * You should have received a copy of the GNU General Public License
- + * along with this program; if not, write to the Free Software
- + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111, USA.
- + *****************************************************************************/
- +
- +#include "muxers.h"
- +
- +typedef struct
- +{
- + FILE *fh;
- + int next_frame;
- + uint64_t plane_size[3];
- +} raw_hnd_t;
- +
- +static int open_file( char *psz_filename, hnd_t *p_handle, video_info_t *info, cli_input_opt_t *opt )
- +{
- + raw_hnd_t *h = malloc( sizeof(raw_hnd_t) );
- + if( !h )
- + return -1;
- +
- + if( !opt->resolution )
- + {
- + /* try to parse the file name */
- + for( char *p = psz_filename; *p; p++ )
- + if( *p >= '0' && *p <= '9' && sscanf( p, "%ux%u", &info->width, &info->height ) == 2 )
- + break;
- + }
- + else
- + sscanf( opt->resolution, "%ux%u", &info->width, &info->height );
- + if( !info->width || !info->height )
- + {
- + fprintf( stderr, "raw [error]: raw input requires a resolution.\n" );
- + return -1;
- + }
- + if( opt->colorspace )
- + {
- + for( info->csp = X264_CSP_CLI_MAX-1; x264_cli_csps[info->csp].name && strcasecmp( x264_cli_csps[info->csp].name, opt->colorspace ); )
- + info->csp--;
- + if( info->csp == X264_CSP_NONE )
- + {
- + fprintf( stderr, "raw [error]: unsupported colorspace '%s'\n", opt->colorspace );
- + fprintf( stderr, "supported colorspaces are i420, i422, i444, yv12, bgr, bgra\n" );
- + return -1;
- + }
- + }
- + else /* default */
- + info->csp = X264_CSP_I420;
- +
- + h->next_frame = 0;
- + info->vfr = 0;
- +
- + if( !strcmp( psz_filename, "-" ) )
- + h->fh = stdin;
- + else
- + h->fh = fopen( psz_filename, "rb" );
- + if( h->fh == NULL )
- + return -1;
- +
- + info->thread_safe = 1;
- + info->num_frames = 0;
- + for( int i = 0; i < x264_cli_csps[info->csp].planes; i++ )
- + h->plane_size[i] = x264_cli_pic_plane_size( info->csp, info->width, info->height, i );
- +
- + if( x264_is_regular_file( h->fh ) )
- + {
- + fseek( h->fh, 0, SEEK_END );
- + uint64_t size = ftell( h->fh );
- + fseek( h->fh, 0, SEEK_SET );
- + info->num_frames = size / x264_cli_pic_size( info->csp, info->width, info->height );
- + }
- +
- + *p_handle = h;
- + return 0;
- +}
- +
- +static int read_frame_internal( cli_pic_t *pic, raw_hnd_t *h )
- +{
- + int error = 0;
- + for( int i = 0; i < pic->img.planes && !error; i++ )
- + error |= fread( pic->img.plane[i], h->plane_size[i], 1, h->fh ) <= 0;
- + return error;
- +}
- +
- +static int read_frame( cli_pic_t *pic, hnd_t handle, int i_frame )
- +{
- + raw_hnd_t *h = handle;
- +
- + if( i_frame > h->next_frame )
- + {
- + if( x264_is_regular_file( h->fh ) )
- + fseek( h->fh, i_frame * x264_cli_pic_size( pic->img.csp, pic->img.width, pic->img.height ), SEEK_SET );
- + else
- + while( i_frame > h->next_frame )
- + {
- + if( read_frame_internal( pic, h ) )
- + return -1;
- + h->next_frame++;
- + }
- + }
- +
- + if( read_frame_internal( pic, h ) )
- + return -1;
- +
- + h->next_frame = i_frame+1;
- + return 0;
- +}
- +
- +static int close_file( hnd_t handle )
- +{
- + raw_hnd_t *h = handle;
- + if( !h || !h->fh )
- + return 0;
- + fclose( h->fh );
- + free( h );
- + return 0;
- +}
- +
- +const cli_input_t raw_input = { open_file, x264_cli_pic_alloc, read_frame, NULL, x264_cli_pic_clean, close_file };
- Index: input/thread.c
- ===================================================================
- --- input/thread_orig.c
- +++ input/thread.c
- @@ -23,13 +23,11 @@
- #include "muxers.h"
- -extern cli_input_t input;
- -
- typedef struct
- {
- cli_input_t input;
- hnd_t p_handle;
- - x264_picture_t pic;
- + cli_pic_t pic;
- x264_pthread_t tid;
- int next_frame;
- int frame_total;
- @@ -40,7 +38,7 @@
- typedef struct thread_input_arg_t
- {
- thread_hnd_t *h;
- - x264_picture_t *pic;
- + cli_pic_t *pic;
- int i_frame;
- int status;
- } thread_input_arg_t;
- @@ -62,7 +60,7 @@
- return -1;
- h->next_args->h = h;
- h->next_args->status = 0;
- - h->frame_total = input.get_frame_total( h->p_handle );
- + h->frame_total = info->num_frames;
- thread_input.picture_alloc = h->input.picture_alloc;
- thread_input.picture_clean = h->input.picture_clean;
- @@ -70,18 +68,12 @@
- return 0;
- }
- -static int get_frame_total( hnd_t handle )
- -{
- - thread_hnd_t *h = handle;
- - return h->frame_total;
- -}
- -
- static void read_frame_thread_int( thread_input_arg_t *i )
- {
- i->status = i->h->input.read_frame( i->pic, i->h->p_handle, i->i_frame );
- }
- -static int read_frame( x264_picture_t *p_pic, hnd_t handle, int i_frame )
- +static int read_frame( cli_pic_t *p_pic, hnd_t handle, int i_frame )
- {
- thread_hnd_t *h = handle;
- int ret = 0;
- @@ -94,7 +86,7 @@
- }
- if( h->next_frame == i_frame )
- - XCHG( x264_picture_t, *p_pic, h->pic );
- + XCHG( cli_pic_t, *p_pic, h->pic );
- else
- ret |= h->input.read_frame( p_pic, h->p_handle, i_frame );
- @@ -113,7 +105,7 @@
- return ret;
- }
- -static int release_frame( x264_picture_t *pic, hnd_t handle )
- +static int release_frame( cli_pic_t *pic, hnd_t handle )
- {
- thread_hnd_t *h = handle;
- if( h->input.release_frame )
- @@ -133,4 +125,4 @@
- return 0;
- }
- -cli_input_t thread_input = { open_file, get_frame_total, NULL, read_frame, release_frame, NULL, close_file };
- +cli_input_t thread_input = { open_file, NULL, read_frame, release_frame, NULL, close_file };
- Index: input/timecode.c
- ===================================================================
- --- input/timecode_orig.c
- +++ input/timecode.c
- @@ -23,18 +23,14 @@
- #include "muxers.h"
- #include <math.h>
- -extern cli_input_t input;
- -
- typedef struct
- {
- cli_input_t input;
- hnd_t p_handle;
- - int frame_total;
- int auto_timebase_num;
- int auto_timebase_den;
- uint64_t timebase_num;
- uint64_t timebase_den;
- - int seek;
- int stored_pts_num;
- int64_t *pts;
- double assume_fps;
- @@ -105,7 +101,6 @@
- {
- char buff[256];
- int ret, tcfv, num, seq_num, timecodes_num;
- - int64_t pts_seek_offset;
- double *timecodes = NULL;
- double *fpss = NULL;
- @@ -120,7 +115,7 @@
- {
- uint64_t file_pos;
- double assume_fps, seq_fps;
- - int start, end = h->seek;
- + int start, end;
- int prev_start = -1, prev_end = -1;
- h->assume_fps = 0;
- @@ -148,7 +143,7 @@
- if( buff[0] == '#' || buff[0] == '\n' || buff[0] == '\r' )
- {
- if( sscanf( buff, "# TDecimate Mode 3: Last Frame = %d", &end ) == 1 )
- - h->stored_pts_num = end + 1 - h->seek;
- + h->stored_pts_num = end + 1;
- continue;
- }
- ret = sscanf( buff, "%d,%d,%lf", &start, &end, &seq_fps );
- @@ -168,8 +163,8 @@
- ++seq_num;
- }
- if( !h->stored_pts_num )
- - h->stored_pts_num = end + 1 - h->seek;
- - timecodes_num = h->stored_pts_num + h->seek;
- + h->stored_pts_num = end + 1;
- + timecodes_num = h->stored_pts_num;
- fseek( tcfile_in, file_pos, SEEK_SET );
- timecodes = malloc( timecodes_num * sizeof(double) );
- @@ -245,20 +240,18 @@
- {
- uint64_t file_pos = ftell( tcfile_in );
- - num = h->stored_pts_num = 0;
- + h->stored_pts_num = 0;
- while( fgets( buff, sizeof(buff), tcfile_in ) != NULL )
- {
- if( buff[0] == '#' || buff[0] == '\n' || buff[0] == '\r' )
- {
- - if( !num )
- + if( !h->stored_pts_num )
- file_pos = ftell( tcfile_in );
- continue;
- }
- - if( num >= h->seek )
- - ++h->stored_pts_num;
- - ++num;
- + h->stored_pts_num++;
- }
- - timecodes_num = h->stored_pts_num + h->seek;
- + timecodes_num = h->stored_pts_num;
- if( !timecodes_num )
- {
- fprintf( stderr, "timecode [error]: input tcfile doesn't have any timecodes!\n" );
- @@ -354,12 +347,10 @@
- h->pts = malloc( h->stored_pts_num * sizeof(int64_t) );
- if( !h->pts )
- goto fail;
- - pts_seek_offset = (int64_t)( timecodes[h->seek] * ((double)h->timebase_den / h->timebase_num) + 0.5 );
- h->pts[0] = 0;
- for( num = 1; num < h->stored_pts_num; num++ )
- {
- - h->pts[num] = (int64_t)( timecodes[h->seek + num] * ((double)h->timebase_den / h->timebase_num) + 0.5 );
- - h->pts[num] -= pts_seek_offset;
- + h->pts[num] = timecodes[num] * ((double)h->timebase_den / h->timebase_num) + 0.5;
- if( h->pts[num] <= h->pts[num - 1] )
- {
- fprintf( stderr, "timecode [error]: invalid timebase or timecode for frame %d\n", num );
- @@ -393,8 +384,6 @@
- }
- h->input = input;
- h->p_handle = *p_handle;
- - h->frame_total = input.get_frame_total( h->p_handle );
- - h->seek = opt->seek;
- if( opt->timebase )
- {
- ret = sscanf( opt->timebase, "%"SCNu64"/%"SCNu64, &h->timebase_num, &h->timebase_den );
- @@ -446,39 +435,38 @@
- return 0;
- }
- -static int get_frame_total( hnd_t handle )
- +static int64_t get_frame_pts( timecode_hnd_t *h, int frame, int real_frame )
- {
- - timecode_hnd_t *h = handle;
- - return h->frame_total;
- -}
- -
- -static int read_frame( x264_picture_t *p_pic, hnd_t handle, int i_frame )
- -{
- - timecode_hnd_t *h = handle;
- - int ret = h->input.read_frame( p_pic, h->p_handle, i_frame );
- -
- - if( i_frame - h->seek < h->stored_pts_num )
- - {
- - assert( i_frame >= h->seek );
- - p_pic->i_pts = h->pts[i_frame - h->seek];
- - }
- + if( frame < h->stored_pts_num )
- + return h->pts[frame];
- else
- {
- - if( h->pts )
- + if( h->pts && real_frame )
- {
- fprintf( stderr, "timecode [info]: input timecode file missing data for frame %d and later\n"
- - " assuming constant fps %.6f\n", i_frame, h->assume_fps );
- + " assuming constant fps %.6f\n", frame, h->assume_fps );
- free( h->pts );
- h->pts = NULL;
- }
- - h->last_timecode += 1 / h->assume_fps;
- - p_pic->i_pts = (int64_t)( h->last_timecode * ((double)h->timebase_den / h->timebase_num) + 0.5 );
- + double timecode = h->last_timecode + 1 / h->assume_fps;
- + if( real_frame )
- + h->last_timecode = timecode;
- + return timecode * ((double)h->timebase_den / h->timebase_num) + 0.5;
- }
- +}
- +
- +static int read_frame( cli_pic_t *pic, hnd_t handle, int frame )
- +{
- + timecode_hnd_t *h = handle;
- + int ret = h->input.read_frame( pic, h->p_handle, frame );
- +
- + pic->pts = get_frame_pts( h, frame, 1 );
- + pic->duration = get_frame_pts( h, frame + 1, 0 ) - pic->pts;
- return ret;
- }
- -static int release_frame( x264_picture_t *pic, hnd_t handle )
- +static int release_frame( cli_pic_t *pic, hnd_t handle )
- {
- timecode_hnd_t *h = handle;
- if( h->input.release_frame )
- @@ -496,4 +485,4 @@
- return 0;
- }
- -cli_input_t timecode_input = { open_file, get_frame_total, NULL, read_frame, release_frame, NULL, close_file };
- +cli_input_t timecode_input = { open_file, NULL, read_frame, release_frame, NULL, close_file };
- Index: input/y4m.c
- ===================================================================
- --- input/y4m_orig.c
- +++ input/y4m.c
- @@ -26,10 +26,11 @@
- typedef struct
- {
- FILE *fh;
- - int width, height;
- int next_frame;
- - int seq_header_len, frame_header_len;
- - int frame_size;
- + int seq_header_len;
- + int frame_header_len;
- + uint64_t frame_size;
- + uint64_t plane_size[3];
- } y4m_hnd_t;
- #define Y4M_MAGIC "YUV4MPEG2"
- @@ -37,6 +38,18 @@
- #define Y4M_FRAME_MAGIC "FRAME"
- #define MAX_FRAME_HEADER 80
- +static int csp_string_to_int( char *csp_name )
- +{
- + int csp = X264_CSP_MAX;
- + if( !strncmp( "420", csp_name, 3 ) )
- + csp = X264_CSP_I420;
- + else if( !strncmp( "422", csp_name, 3 ) )
- + csp = X264_CSP_I422;
- + else if( !strncmp( "444", csp_name, 3 ) )
- + csp = X264_CSP_I444;
- + return csp;
- +}
- +
- static int open_file( char *psz_filename, hnd_t *p_handle, video_info_t *info, cli_input_opt_t *opt )
- {
- y4m_hnd_t *h = malloc( sizeof(y4m_hnd_t) );
- @@ -87,18 +100,15 @@
- switch( *tokstart++ )
- {
- case 'W': /* Width. Required. */
- - h->width = info->width = strtol( tokstart, &tokend, 10 );
- + info->width = strtol( tokstart, &tokend, 10 );
- tokstart=tokend;
- break;
- case 'H': /* Height. Required. */
- - h->height = info->height = strtol( tokstart, &tokend, 10 );
- + info->height = strtol( tokstart, &tokend, 10 );
- tokstart=tokend;
- break;
- case 'C': /* Color space */
- - if( !strncmp( "420", tokstart, 3 ) )
- - colorspace = X264_CSP_I420;
- - else
- - colorspace = X264_CSP_MAX; ///< anything other than 420 since we don't handle it
- + colorspace = csp_string_to_int( tokstart );
- tokstart = strchr( tokstart, 0x20 );
- break;
- case 'I': /* Interlace type */
- @@ -145,10 +155,7 @@
- {
- /* Older nonstandard pixel format representation */
- tokstart += 6;
- - if( !strncmp( "420",tokstart, 3 ) )
- - alt_colorspace = X264_CSP_I420;
- - else
- - alt_colorspace = X264_CSP_MAX;
- + alt_colorspace = csp_string_to_int( tokstart );
- }
- tokstart = strchr( tokstart, 0x20 );
- break;
- @@ -162,36 +169,37 @@
- if( colorspace == X264_CSP_NONE )
- colorspace = X264_CSP_I420;
- - if( colorspace != X264_CSP_I420 )
- + if( colorspace <= X264_CSP_NONE && colorspace >= X264_CSP_MAX )
- {
- fprintf( stderr, "y4m [error]: colorspace unhandled\n" );
- return -1;
- }
- - *p_handle = h;
- - return 0;
- -}
- -
- -/* Most common case: frame_header = "FRAME" */
- -static int get_frame_total( hnd_t handle )
- -{
- - y4m_hnd_t *h = handle;
- - int i_frame_total = 0;
- + info->thread_safe = 1;
- + info->num_frames = 0;
- + info->csp = colorspace;
- + h->frame_size = h->frame_header_len;
- + for( i = 0; i < x264_cli_csps[info->csp].planes; i++ )
- + {
- + h->plane_size[i] = x264_cli_pic_plane_size( info->csp, info->width, info->height, i );
- + h->frame_size += h->plane_size[i];
- + }
- + /* Most common case: frame_header = "FRAME" */
- if( x264_is_regular_file( h->fh ) )
- {
- uint64_t init_pos = ftell( h->fh );
- fseek( h->fh, 0, SEEK_END );
- uint64_t i_size = ftell( h->fh );
- fseek( h->fh, init_pos, SEEK_SET );
- - i_frame_total = (int)((i_size - h->seq_header_len) /
- - (3*(h->width*h->height)/2+h->frame_header_len));
- + info->num_frames = (i_size - h->seq_header_len) / h->frame_size;
- }
- - return i_frame_total;
- + *p_handle = h;
- + return 0;
- }
- -static int read_frame_internal( x264_picture_t *p_pic, y4m_hnd_t *h )
- +static int read_frame_internal( cli_pic_t *pic, y4m_hnd_t *h )
- {
- int slen = strlen( Y4M_FRAME_MAGIC );
- int i = 0;
- @@ -218,34 +226,32 @@
- return -1;
- }
- h->frame_header_len = i+slen+1;
- + h->frame_size = x264_cli_pic_size( pic->img.csp, pic->img.width, pic->img.height ) + h->frame_header_len;
- - if( fread( p_pic->img.plane[0], h->width * h->height, 1, h->fh ) <= 0
- - || fread( p_pic->img.plane[1], h->width * h->height / 4, 1, h->fh ) <= 0
- - || fread( p_pic->img.plane[2], h->width * h->height / 4, 1, h->fh ) <= 0 )
- - return -1;
- -
- - return 0;
- + int error = 0;
- + for( i = 0; i < pic->img.planes && !error; i++ )
- + error |= fread( pic->img.plane[i], h->plane_size[i], 1, h->fh ) <= 0;
- + return error;
- }
- -static int read_frame( x264_picture_t *p_pic, hnd_t handle, int i_frame )
- +static int read_frame( cli_pic_t *pic, hnd_t handle, int i_frame )
- {
- y4m_hnd_t *h = handle;
- if( i_frame > h->next_frame )
- {
- if( x264_is_regular_file( h->fh ) )
- - fseek( h->fh, (uint64_t)i_frame*(3*(h->width*h->height)/2+h->frame_header_len)
- - + h->seq_header_len, SEEK_SET );
- + fseek( h->fh, h->frame_size * i_frame + h->seq_header_len, SEEK_SET );
- else
- while( i_frame > h->next_frame )
- {
- - if( read_frame_internal( p_pic, h ) )
- + if( read_frame_internal( pic, h ) )
- return -1;
- h->next_frame++;
- }
- }
- - if( read_frame_internal( p_pic, h ) )
- + if( read_frame_internal( pic, h ) )
- return -1;
- h->next_frame = i_frame+1;
- @@ -262,4 +268,4 @@
- return 0;
- }
- -const cli_input_t y4m_input = { open_file, get_frame_total, x264_picture_alloc, read_frame, NULL, x264_picture_clean, close_file };
- +const cli_input_t y4m_input = { open_file, x264_cli_pic_alloc, read_frame, NULL, x264_cli_pic_clean, close_file };
- Index: input/yuv.c
- ===================================================================
- --- input/yuv.c
- +++ /dev/null
- @@ -1,127 +0,0 @@
- -/*****************************************************************************
- - * yuv.c: x264 yuv input module
- - *****************************************************************************
- - * Copyright (C) 2003-2009 x264 project
- - *
- - * Authors: Laurent Aimar <fenrir@via.ecp.fr>
- - * Loren Merritt <lorenm@u.washington.edu>
- - *
- - * This program is free software; you can redistribute it and/or modify
- - * it under the terms of the GNU General Public License as published by
- - * the Free Software Foundation; either version 2 of the License, or
- - * (at your option) any later version.
- - *
- - * This program 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 General Public License for more details.
- - *
- - * You should have received a copy of the GNU General Public License
- - * along with this program; if not, write to the Free Software
- - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111, USA.
- - *****************************************************************************/
- -
- -#include "muxers.h"
- -
- -typedef struct
- -{
- - FILE *fh;
- - int width, height;
- - int next_frame;
- -} yuv_hnd_t;
- -
- -static int open_file( char *psz_filename, hnd_t *p_handle, video_info_t *info, cli_input_opt_t *opt )
- -{
- - yuv_hnd_t *h = malloc( sizeof(yuv_hnd_t) );
- - if( !h )
- - return -1;
- -
- - if( !opt->resolution )
- - {
- - /* try to parse the file name */
- - for( char *p = psz_filename; *p; p++ )
- - if( *p >= '0' && *p <= '9' && sscanf( p, "%ux%u", &info->width, &info->height ) == 2 )
- - break;
- - }
- - else
- - sscanf( opt->resolution, "%ux%u", &info->width, &info->height );
- - if( !info->width || !info->height )
- - {
- - fprintf( stderr, "yuv [error]: rawyuv input requires a resolution.\n" );
- - return -1;
- - }
- -
- - h->next_frame = 0;
- - info->vfr = 0;
- - h->width = info->width;
- - h->height = info->height;
- -
- - if( !strcmp( psz_filename, "-" ) )
- - h->fh = stdin;
- - else
- - h->fh = fopen( psz_filename, "rb" );
- - if( h->fh == NULL )
- - return -1;
- -
- - *p_handle = h;
- - return 0;
- -}
- -
- -static int get_frame_total( hnd_t handle )
- -{
- - yuv_hnd_t *h = handle;
- - int i_frame_total = 0;
- -
- - if( x264_is_regular_file( h->fh ) )
- - {
- - fseek( h->fh, 0, SEEK_END );
- - uint64_t i_size = ftell( h->fh );
- - fseek( h->fh, 0, SEEK_SET );
- - i_frame_total = (int)(i_size / ( h->width * h->height * 3 / 2 ));
- - }
- -
- - return i_frame_total;
- -}
- -
- -static int read_frame_internal( x264_picture_t *p_pic, yuv_hnd_t *h )
- -{
- - return fread( p_pic->img.plane[0], h->width * h->height, 1, h->fh ) <= 0
- - || fread( p_pic->img.plane[1], h->width * h->height / 4, 1, h->fh ) <= 0
- - || fread( p_pic->img.plane[2], h->width * h->height / 4, 1, h->fh ) <= 0;
- -}
- -
- -static int read_frame( x264_picture_t *p_pic, hnd_t handle, int i_frame )
- -{
- - yuv_hnd_t *h = handle;
- -
- - if( i_frame > h->next_frame )
- - {
- - if( x264_is_regular_file( h->fh ) )
- - fseek( h->fh, (uint64_t)i_frame * h->width * h->height * 3 / 2, SEEK_SET );
- - else
- - while( i_frame > h->next_frame )
- - {
- - if( read_frame_internal( p_pic, h ) )
- - return -1;
- - h->next_frame++;
- - }
- - }
- -
- - if( read_frame_internal( p_pic, h ) )
- - return -1;
- -
- - h->next_frame = i_frame+1;
- - return 0;
- -}
- -
- -static int close_file( hnd_t handle )
- -{
- - yuv_hnd_t *h = handle;
- - if( !h || !h->fh )
- - return 0;
- - fclose( h->fh );
- - free( h );
- - return 0;
- -}
- -
- -const cli_input_t yuv_input = { open_file, get_frame_total, x264_picture_alloc, read_frame, NULL, x264_picture_clean, close_file };
- Index: x264.c
- ===================================================================
- --- x264_orig.c
- +++ x264.c
- @@ -34,6 +34,7 @@
- #include "common/cpu.h"
- #include "x264.h"
- #include "muxers.h"
- +#include "filter/filter.h"
- #ifdef _WIN32
- #include <windows.h>
- @@ -66,10 +67,13 @@
- cli_input_t input;
- static cli_output_t output;
- +/* video filter operation function pointer struct */
- +static cli_vid_filter_t filter;
- +
- static const char * const demuxer_names[] =
- {
- "auto",
- - "yuv",
- + "raw",
- "y4m",
- #ifdef AVS_INPUT
- "avs",
- @@ -209,10 +213,10 @@
- #define H1 if(longhelp>=1) printf
- #define H2 if(longhelp==2) printf
- H0( "x264 core:%d%s\n"
- - "Syntax: x264 [options] -o outfile infile [widthxheight]\n"
- + "Syntax: x264 [options] -o outfile infile\n"
- "\n"
- - "Infile can be raw YUV 4:2:0 (in which case resolution is required),\n"
- - " or YUV4MPEG 4:2:0 (*.y4m),\n"
- + "Infile can be raw (in which case resolution is required),\n"
- + " or YUV4MPEG (*.y4m),\n"
- " or Avisynth if compiled with support (%s).\n"
- " or libav* formats if compiled with lavf support (%s) or ffms support (%s).\n"
- "Outfile type is selected by filename:\n"
- @@ -566,6 +570,8 @@
- " - %s\n", muxer_names[0], stringify_names( buf, muxer_names ) );
- H1( " --demuxer <string> Specify input container format [\"%s\"]\n"
- " - %s\n", demuxer_names[0], stringify_names( buf, demuxer_names ) );
- + H1( " --input-csp <string> Specify input colorspace format\n" );
- + H1( " --input-res <intxint> Specify input resolution (width x height)\n" );
- H1( " --index <string> Filename for input index file\n" );
- H0( " --sar width:height Specify Sample Aspect Ratio\n" );
- H0( " --fps <float|rational> Specify framerate\n" );
- @@ -597,6 +603,13 @@
- " <integer> Specify timebase numerator for input timecode file\n"
- " or specify timebase denominator for other input\n" );
- H0( "\n" );
- + H0( "Filtering:\n" );
- + H0( "\n" );
- + H0( "--vf, --video-filter <filter0>/<filter1>/... Apply video filtering to the input file\n" );
- + H0( " Available filters:\n" );
- + x264_register_vid_filters();
- + x264_vid_filter_help( longhelp );
- + H0( "\n" );
- }
- #define OPT_FRAMES 256
- @@ -622,6 +635,9 @@
- #define OPT_TIMEBASE 276
- #define OPT_PULLDOWN 277
- #define OPT_DEMUXER_THREADS 278
- +#define OPT_VIDEO_FILTER 279
- +#define OPT_INPUT_RES 280
- +#define OPT_INPUT_CSP 281
- static char short_options[] = "8A:B:b:f:hI:i:m:o:p:q:r:t:Vvw";
- static struct option long_options[] =
- @@ -769,6 +785,10 @@
- { "nal-hrd", required_argument, NULL, 0 },
- { "pulldown", required_argument, NULL, OPT_PULLDOWN },
- { "fake-interlaced", no_argument, NULL, 0 },
- + { "vf", required_argument, NULL, OPT_VIDEO_FILTER },
- + { "video-filter", required_argument, NULL, OPT_VIDEO_FILTER },
- + { "input-res", required_argument, NULL, OPT_INPUT_RES },
- + { "input-csp", required_argument, NULL, OPT_INPUT_CSP },
- {0, 0, 0, 0}
- };
- @@ -838,7 +858,7 @@
- int b_regular = strcmp( filename, "-" );
- int b_auto = !strcasecmp( demuxer, "auto" );
- if( !b_regular && b_auto )
- - ext = "yuv";
- + ext = "raw";
- if( b_regular )
- {
- FILE *f = fopen( filename, "r" );
- @@ -862,8 +882,8 @@
- }
- else if( !strcasecmp( module, "y4m" ) )
- input = y4m_input;
- - else if( !strcasecmp( module, "yuv" ) )
- - input = yuv_input;
- + else if( !strcasecmp( module, "raw" ) )
- + input = raw_input;
- else
- {
- #ifdef FFMS_INPUT
- @@ -893,11 +913,11 @@
- input = avs_input;
- }
- #endif
- - if( b_auto && !yuv_input.open_file( filename, p_handle, info, opt ) )
- + if( b_auto && !raw_input.open_file( filename, p_handle, info, opt ) )
- {
- - module = "yuv";
- + module = "raw";
- b_auto = 0;
- - input = yuv_input;
- + input = raw_input;
- }
- if( !(*p_handle) )
- @@ -911,6 +931,49 @@
- return 0;
- }
- +int init_vid_filters( char *sequence, hnd_t *handle, video_info_t *info, x264_param_t *param )
- +{
- + x264_register_vid_filters();
- +
- + /* intialize baseline filters */
- + if( x264_init_vid_filter( "source", handle, &filter, info, param, NULL ) ) /* wrap demuxer into a filter */
- + return -1;
- + if( x264_init_vid_filter( "resize", handle, &filter, info, param, "normcsp" ) ) /* normalize csps to be of a known/supported format */
- + return -1;
- + if( x264_init_vid_filter( "fix_vfr_pts", handle, &filter, info, param, NULL ) ) /* fix vfr pts */
- + return -1;
- +
- + /* parse filter chain */
- + for( char *p = sequence; p && *p; )
- + {
- + int tok_len = strcspn( p, "/" );
- + int p_len = strlen( p );
- + p[tok_len] = 0;
- + int name_len = strcspn( p, ":" );
- + if( name_len == tok_len )
- + {
- + fprintf( stderr, "x264 [error]: invalid filter format `%s'\n", p );
- + return -1;
- + }
- + p[name_len++] = 0;
- + if( x264_init_vid_filter( p, handle, &filter, info, param, p + name_len ) )
- + return -1;
- + p += X264_MIN( tok_len+1, p_len );
- + }
- +
- + /* force end result resolution */
- + if( !param->i_width && !param->i_height )
- + {
- + param->i_height = info->height;
- + param->i_width = info->width;
- + }
- + info->dst_csp = param->i_csp; /* force end result colorspace */
- + if( x264_init_vid_filter( "resize", handle, &filter, info, param, NULL ) )
- + return -1;
- +
- + return 0;
- +}
- +
- static int parse_enum_name( const char *arg, const char * const *names, const char **dst )
- {
- for( int i = 0; names[i]; i++ )
- @@ -945,6 +1008,7 @@
- char *tcfile_name = NULL;
- x264_param_t defaults;
- char *profile = NULL;
- + char *vid_filters = NULL;
- int b_thread_input = 0;
- int i_demuxer_threads = 1;
- int b_turbo = 1;
- @@ -1112,6 +1176,15 @@
- if( parse_enum_value( optarg, pulldown_names, &opt->i_pulldown ) < 0 )
- return -1;
- break;
- + case OPT_VIDEO_FILTER:
- + vid_filters = optarg;
- + break;
- + case OPT_INPUT_RES:
- + input_opt.resolution = optarg;
- + break;
- + case OPT_INPUT_CSP:
- + input_opt.colorspace = optarg;
- + break;
- default:
- generic_option:
- {
- @@ -1167,13 +1240,13 @@
- }
- input_filename = argv[optind++];
- - input_opt.resolution = optind < argc ? argv[optind++] : NULL;
- input_opt.demuxer_threads = X264_MAX( i_demuxer_threads, 1 );
- video_info_t info = {0};
- char demuxername[5];
- /* set info flags to param flags to be overwritten by demuxer as necessary. */
- info.csp = param->i_csp;
- + info.dst_csp = param->i_csp;
- info.fps_num = param->i_fps_num;
- info.fps_den = param->i_fps_den;
- info.interlaced = param->b_interlaced;
- @@ -1210,8 +1283,7 @@
- fprintf( stderr, "x264 [error]: timecode input failed\n" );
- return -1;
- }
- - else
- - input = timecode_input;
- + input = timecode_input;
- }
- else if( !info.vfr && input_opt.timebase )
- {
- @@ -1219,11 +1291,34 @@
- return -1;
- }
- + /* init threaded input while input info is unaltered by filtering */
- +#ifdef HAVE_PTHREAD
- + if( info.thread_safe && (b_thread_input || param->i_threads > 1
- + || (param->i_threads == X264_THREADS_AUTO && x264_cpu_num_processors() > 1)) )
- + {
- + if( thread_input.open_file( NULL, &opt->hin, &info, NULL ) )
- + {
- + fprintf( stderr, "x264 [error]: threaded input failed\n" );
- + return -1;
- + }
- + input = thread_input;
- + }
- +#endif
- +
- /* set param flags from the info flags as necessary */
- - param->i_csp = info.csp;
- - param->i_height = info.height;
- + param->i_csp = info.dst_csp;
- +
- + if( init_vid_filters( vid_filters, &opt->hin, &info, param ) )
- + return -1;
- +
- param->b_vfr_input = info.vfr;
- - param->i_width = info.width;
- +
- + info.num_frames = X264_MAX( info.num_frames - opt->i_seek, 0 );
- + if( (!info.num_frames || param->i_frame_total < info.num_frames)
- + && param->i_frame_total > 0 )
- + info.num_frames = param->i_frame_total;
- + param->i_frame_total = info.num_frames;
- +
- if( !b_user_interlaced && info.interlaced )
- {
- fprintf( stderr, "x264 [warning]: input appears to be interlaced, enabling %cff interlaced mode.\n"
- @@ -1279,21 +1374,6 @@
- param->vui.i_sar_height = info.sar_height;
- }
- -#ifdef HAVE_PTHREAD
- - if( b_thread_input || param->i_threads > 1
- - || (param->i_threads == X264_THREADS_AUTO && x264_cpu_num_processors() > 1) )
- - {
- - if( thread_input.open_file( NULL, &opt->hin, &info, NULL ) )
- - {
- - fprintf( stderr, "x264 [error]: threaded input failed\n" );
- - return -1;
- - }
- - else
- - input = thread_input;
- - }
- -#endif
- -
- -
- /* Automatically reduce reference frame count to match the user's target level
- * if the user didn't explicitly set a reference frame count. */
- if( !b_user_ref )
- @@ -1407,13 +1487,23 @@
- fflush( stderr ); // needed in windows
- }
- +static void Convert_cli_to_lib_pic( x264_picture_t *lib, cli_pic_t *cli )
- +{
- + memcpy( lib->img.i_stride, cli->img.stride, sizeof(cli->img.stride) );
- + memcpy( lib->img.plane, cli->img.plane, sizeof(cli->img.plane) );
- + lib->img.i_plane = cli->img.planes;
- + lib->img.i_csp = cli->img.csp;
- + lib->i_pts = cli->pts;
- +}
- +
- static int Encode( x264_param_t *param, cli_opt_t *opt )
- {
- x264_t *h;
- x264_picture_t pic;
- + cli_pic_t cli_pic;
- const cli_pulldown_t *pulldown = NULL; // shut up gcc
- - int i_frame, i_frame_total, i_frame_output;
- + int i_frame, i_frame_output;
- int64_t i_start, i_end;
- int64_t i_file = 0;
- int i_frame_size;
- @@ -1432,13 +1522,8 @@
- double pulldown_pts = 0;
- opt->b_progress &= param->i_log_level < X264_LOG_DEBUG;
- - i_frame_total = input.get_frame_total( opt->hin );
- - i_frame_total = X264_MAX( i_frame_total - opt->i_seek, 0 );
- - if( ( i_frame_total == 0 || param->i_frame_total < i_frame_total )
- - && param->i_frame_total > 0 )
- - i_frame_total = param->i_frame_total;
- - param->i_frame_total = i_frame_total;
- - i_update_interval = i_frame_total ? x264_clip3( i_frame_total / 1000, 1, 10 ) : 10;
- + i_update_interval = param->i_frame_total ? x264_clip3( param->i_frame_total / 1000, 1, 10 ) : 10;
- + x264_picture_defaults( &pic );
- /* set up pulldown */
- if( opt->i_pulldown && !param->b_vfr_input )
- @@ -1457,7 +1542,7 @@
- if( ( h = x264_encoder_open( param ) ) == NULL )
- {
- fprintf( stderr, "x264 [error]: x264_encoder_open failed\n" );
- - input.close_file( opt->hin );
- + filter.free( opt->hin );
- return -1;
- }
- @@ -1468,18 +1553,11 @@
- if( output.set_param( opt->hout, param ) )
- {
- fprintf( stderr, "x264 [error]: can't set outfile param\n" );
- - input.close_file( opt->hin );
- + filter.free( opt->hin );
- output.close_file( opt->hout, largest_pts, second_largest_pts );
- return -1;
- }
- - /* Create a new pic */
- - if( input.picture_alloc( &pic, param->i_csp, param->i_width, param->i_height ) )
- - {
- - fprintf( stderr, "x264 [error]: malloc failed\n" );
- - return -1;
- - }
- -
- i_start = x264_mdate();
- /* ticks/frame = ticks/second / frames/second */
- ticks_per_frame = (int64_t)param->i_timebase_den * param->i_fps_den / param->i_timebase_num / param->i_fps_num;
- @@ -1509,10 +1587,11 @@
- fprintf( opt->tcfile_out, "# timecode format v2\n" );
- /* Encode frames */
- - for( i_frame = 0, i_frame_output = 0; b_ctrl_c == 0 && (i_frame < i_frame_total || i_frame_total == 0); )
- + for( i_frame = 0, i_frame_output = 0; !b_ctrl_c && (i_frame < param->i_frame_total || !param->i_frame_total); i_frame++ )
- {
- - if( input.read_frame( &pic, opt->hin, i_frame + opt->i_seek ) )
- + if( filter.get_frame( opt->hin, &cli_pic, i_frame + opt->i_seek ) )
- break;
- + Convert_cli_to_lib_pic( &pic, &cli_pic );
- if( !param->b_vfr_input )
- pic.i_pts = i_frame;
- @@ -1569,14 +1648,12 @@
- first_dts = prev_dts = last_dts;
- }
- - i_frame++;
- -
- - if( input.release_frame && input.release_frame( &pic, opt->hin ) )
- + if( filter.release_frame( opt->hin, &cli_pic, i_frame + opt->i_seek ) )
- break;
- /* update status line (up to 1000 times per input file) */
- if( opt->b_progress && i_frame_output % i_update_interval == 0 && i_frame_output )
- - Print_status( i_start, i_frame_output, i_frame_total, i_file, param, 2 * last_dts - prev_dts - first_dts );
- + Print_status( i_start, i_frame_output, param->i_frame_total, i_file, param, 2 * last_dts - prev_dts - first_dts );
- }
- /* Flush delayed frames */
- while( !b_ctrl_c && x264_encoder_delayed_frames( h ) )
- @@ -1593,7 +1670,7 @@
- first_dts = prev_dts = last_dts;
- }
- if( opt->b_progress && i_frame_output % i_update_interval == 0 && i_frame_output )
- - Print_status( i_start, i_frame_output, i_frame_total, i_file, param, 2 * last_dts - prev_dts - first_dts );
- + Print_status( i_start, i_frame_output, param->i_frame_total, i_file, param, 2 * last_dts - prev_dts - first_dts );
- }
- if( pts_warning_cnt >= MAX_PTS_WARNING && param->i_log_level < X264_LOG_DEBUG )
- fprintf( stderr, "x264 [warning]: %d suppressed nonmonotonic pts warnings\n", pts_warning_cnt-MAX_PTS_WARNING );
- @@ -1609,7 +1686,6 @@
- duration *= dts_compress_multiplier;
- i_end = x264_mdate();
- - input.picture_clean( &pic );
- /* Erase progress indicator before printing encoding stats. */
- if( opt->b_progress )
- fprintf( stderr, " \r" );
- @@ -1625,7 +1701,7 @@
- opt->tcfile_out = NULL;
- }
- - input.close_file( opt->hin );
- + filter.free( opt->hin );
- output.close_file( opt->hout, largest_pts, second_largest_pts );
- if( i_frame_output > 0 )
- Index: x264.h
- ===================================================================
- --- x264_orig.h
- +++ x264.h
- @@ -35,7 +35,7 @@
- #include <stdarg.h>
- -#define X264_BUILD 96
- +#define X264_BUILD 97
- /* x264_t:
- * opaque handler for encoder */
- @@ -123,12 +123,8 @@
- #define X264_CSP_I420 0x0001 /* yuv 4:2:0 planar */
- #define X264_CSP_I422 0x0002 /* yuv 4:2:2 planar */
- #define X264_CSP_I444 0x0003 /* yuv 4:4:4 planar */
- -#define X264_CSP_YV12 0x0004 /* yuv 4:2:0 planar */
- -#define X264_CSP_YUYV 0x0005 /* yuv 4:2:2 packed */
- -#define X264_CSP_RGB 0x0006 /* rgb 24bits */
- -#define X264_CSP_BGR 0x0007 /* bgr 24bits */
- -#define X264_CSP_BGRA 0x0008 /* bgr 32bits */
- -#define X264_CSP_MAX 0x0009 /* end of list */
- +#define X264_CSP_YV12 0x0004 /* yvu 4:2:0 planar */
- +#define X264_CSP_MAX 0x0005 /* end of list */
- #define X264_CSP_VFLIP 0x1000 /* */
- /* Slice type */
- @@ -548,6 +544,10 @@
- not even copy it from input to output frames. */
- void *opaque;
- } x264_picture_t;
- +
- +/* x264_picture_defaults:
- + * set the picture's values to the defaults. */
- +void x264_picture_defaults( x264_picture_t *pic );
- /* x264_picture_alloc:
- * alloc data for a picture. You must call x264_picture_clean on it.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement