diff options
Diffstat (limited to 'src/dxr3')
-rw-r--r-- | src/dxr3/Makefile.am | 44 | ||||
-rw-r--r-- | src/dxr3/dxr3.h | 22 | ||||
-rw-r--r-- | src/dxr3/dxr3_decode_spu.c | 55 | ||||
-rw-r--r-- | src/dxr3/dxr3_decode_video.c | 56 | ||||
-rw-r--r-- | src/dxr3/dxr3_mpeg_encoders.c | 53 | ||||
-rw-r--r-- | src/dxr3/dxr3_scr.h | 2 | ||||
-rw-r--r-- | src/dxr3/ffmpeg_encoder.c | 339 | ||||
-rw-r--r-- | src/dxr3/video_out_dxr3.c | 83 | ||||
-rw-r--r-- | src/dxr3/video_out_dxr3.h | 4 |
9 files changed, 439 insertions, 219 deletions
diff --git a/src/dxr3/Makefile.am b/src/dxr3/Makefile.am index fadb8b736..b904c899a 100644 --- a/src/dxr3/Makefile.am +++ b/src/dxr3/Makefile.am @@ -1,18 +1,18 @@ +include $(top_srcdir)/misc/Makefile.quiet include $(top_builddir)/misc/Makefile.plugins include $(top_srcdir)/misc/Makefile.common -AM_CFLAGS = $(X_CFLAGS) $(LIBFAME_CFLAGS) +AM_CFLAGS = $(DEFAULT_OCFLAGS) $(VISIBILITY_FLAG) +AM_CPPFLAGS = +AM_LDFLAGS = $(xineplug_ldflags) -if HAVE_DXR3 -dxr3_modules = xineplug_decode_dxr3_video.la \ - xineplug_decode_dxr3_spu.la \ - xineplug_vo_out_dxr3.la -endif if HAVE_X11 +AM_CFLAGS += $(X_CFLAGS) link_x_libs = $(X_LIBS) -lXext endif if HAVE_LIBFAME -link_fame = $(LIBFAME_LIBS) +AM_CFLAGS += $(LIBFAME_CFLAGS) +link_fame = $(LIBFAME_LIBS) endif if HAVE_LIBRTE link_rte = -lrte @@ -20,37 +20,33 @@ endif EXTRA_DIST = compat.c -xineplug_LTLIBRARIES = $(dxr3_modules) +noinst_HEADERS = em8300.h dxr3.h dxr3_scr.h video_out_dxr3.h + +if ENABLE_DXR3 +xineplug_LTLIBRARIES = xineplug_decode_dxr3_video.la \ + xineplug_decode_dxr3_spu.la \ + xineplug_vo_out_dxr3.la +endif xineplug_decode_dxr3_video_la_SOURCES = dxr3_decode_video.c xineplug_decode_dxr3_video_la_LIBADD = $(XINE_LIB) $(LTLIBINTL) -xineplug_decode_dxr3_video_la_CFLAGS = $(VISIBILITY_FLAG) $(AM_CFLAGS) -xineplug_decode_dxr3_video_la_LDFLAGS = $(xineplug_ldflags) -if HAVE_DVDNAV -AM_CPPFLAGS = $(DVDNAV_CFLAGS) +if WITH_EXTERNAL_DVDNAV xineplug_decode_dxr3_spu_la_SOURCES = dxr3_decode_spu.c xineplug_decode_dxr3_spu_la_LIBADD = $(XINE_LIB) $(LTLIBINTL) $(DVDNAV_LIBS) +xineplug_decode_dxr3_spu_la_CFLAGS = $(AM_CFLAGS) $(DVDNAV_CFLAGS) else -AM_CPPFLAGS = -I$(top_srcdir)/src/input/libdvdnav xineplug_decode_dxr3_spu_la_SOURCES = dxr3_decode_spu.c nav_read.c xineplug_decode_dxr3_spu_la_LIBADD = $(XINE_LIB) $(LTLIBINTL) +xineplug_decode_dxr3_spu_la_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/src/input/libdvdnav endif -xineplug_decode_dxr3_spu_la_CFLAGS = $(VISIBILITY_FLAG) $(AM_CFLAGS) -xineplug_decode_dxr3_spu_la_LDFLAGS = $(xineplug_ldflags) xineplug_vo_out_dxr3_la_SOURCES = \ dxr3_mpeg_encoders.c \ + ffmpeg_encoder.c \ dxr3_spu_encoder.c \ dxr3_scr.c \ video_out_dxr3.c -xineplug_vo_out_dxr3_la_LIBADD = $(XINE_LIB) $(link_fame) $(link_rte) $(link_x_libs) $(LTLIBINTL) $(DYNAMIC_LD_LIBS) -lm -xineplug_vo_out_dxr3_la_CFLAGS = $(VISIBILITY_FLAG) $(AM_CFLAGS) -xineplug_vo_out_dxr3_la_LDFLAGS = $(xineplug_ldflags) - -noinst_HEADERS = \ - em8300.h \ - dxr3.h \ - dxr3_scr.h \ - video_out_dxr3.h +xineplug_vo_out_dxr3_la_CFLAGS = $(AM_CFLAGS) $(AVUTIL_CFLAGS) $(FFMPEG_CFLAGS) +xineplug_vo_out_dxr3_la_LIBADD = $(XINE_LIB) $(link_fame) $(link_rte) $(link_x_libs) $(LTLIBINTL) $(AVUTIL_LIBS) $(FFMPEG_LIBS) -lm diff --git a/src/dxr3/dxr3.h b/src/dxr3/dxr3.h index 78e74a7b4..be151d055 100644 --- a/src/dxr3/dxr3.h +++ b/src/dxr3/dxr3.h @@ -23,7 +23,11 @@ #include "em8300.h" -#include "xine_internal.h" +#include <xine/xine_internal.h> + +#ifndef LOG_VID +#define LOG_VID 0 +#endif /* data for the device name config entry */ #define CONF_KEY "dxr3.device_number" @@ -37,5 +41,19 @@ * (used by decoders to check for dxr3 presence) */ #define DXR3_VO_ID "dxr3" -#endif +/* inline helper implementations */ +static inline int dxr3_present(xine_stream_t *stream) +{ + int present = 0; + + if (stream->video_driver && stream->video_driver->node && + stream->video_driver->node->plugin_class ) { + const video_driver_class_t *const vo_class = (video_driver_class_t *)stream->video_driver->node->plugin_class; + if (vo_class->identifier) + present = (strcmp(vo_class->identifier, DXR3_VO_ID) == 0); + } + llprintf(LOG_VID, "dxr3 %s\n", present ? "present" : "not present"); + return present; +} +#endif diff --git a/src/dxr3/dxr3_decode_spu.c b/src/dxr3/dxr3_decode_spu.c index 100ba7674..0dc024253 100644 --- a/src/dxr3/dxr3_decode_spu.c +++ b/src/dxr3/dxr3_decode_spu.c @@ -46,9 +46,9 @@ #define LOG_SPU 0 #define LOG_BTN 0 -#include "xine_internal.h" -#include "xineutils.h" -#include "buffer.h" +#include <xine/xine_internal.h> +#include <xine/xineutils.h> +#include <xine/buffer.h> #include "xine-engine/bswap.h" #ifdef HAVE_DVDNAV # ifdef HAVE_DVDNAV_NAVTYPES_H @@ -75,7 +75,7 @@ static void *dxr3_spudec_init_plugin(xine_t *xine, void *); /* plugin catalog information */ -static uint32_t supported_types[] = { BUF_SPU_DVD, 0 }; +static const uint32_t supported_types[] = { BUF_SPU_DVD, 0 }; static const decoder_info_t dxr3_spudec_info = { supported_types, /* supported types */ @@ -84,16 +84,13 @@ static const decoder_info_t dxr3_spudec_info = { const plugin_info_t xine_plugin_info[] EXPORTED = { /* type, API, "name", version, special_info, init_function */ - { PLUGIN_SPU_DECODER, 16, "dxr3-spudec", XINE_VERSION_CODE, &dxr3_spudec_info, &dxr3_spudec_init_plugin }, + { PLUGIN_SPU_DECODER, 17, "dxr3-spudec", XINE_VERSION_CODE, &dxr3_spudec_info, &dxr3_spudec_init_plugin }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; /* plugin class functions */ static spu_decoder_t *dxr3_spudec_open_plugin(spu_decoder_class_t *class_gen, xine_stream_t *stream); -static char *dxr3_spudec_get_identifier(spu_decoder_class_t *class_gen); -static char *dxr3_spudec_get_description(spu_decoder_class_t *class_gen); -static void dxr3_spudec_class_dispose(spu_decoder_class_t *class_gen); /* plugin instance functions */ static void dxr3_spudec_decode_data(spu_decoder_t *this_gen, buf_element_t *buf); @@ -156,24 +153,6 @@ static int dxr3_spudec_copy_nav_to_btn(dxr3_spudec_t *this, int32_t mode static inline void dxr3_swab_clut(int* clut); /* inline helper implementations */ -static inline int dxr3_present(xine_stream_t *stream) -{ - plugin_node_t *node; - video_driver_class_t *vo_class; - int present = 0; - - if (stream->video_driver && stream->video_driver->node) { - node = (plugin_node_t *)stream->video_driver->node; - if (node->plugin_class) { - vo_class = (video_driver_class_t *)node->plugin_class; - if (vo_class->get_identifier) - present = (strcmp(vo_class->get_identifier(vo_class), DXR3_VO_ID) == 0); - } - } - llprintf(LOG_SPU, "dxr3 %s\n", present ? "present" : "not present"); - return present; -} - static inline void dxr3_spudec_clear_nav_list(dxr3_spudec_t *this) { while (this->pci_cur.next) { @@ -213,9 +192,9 @@ static void *dxr3_spudec_init_plugin(xine_t *xine, void* data) if (!this) return NULL; this->spu_decoder_class.open_plugin = dxr3_spudec_open_plugin; - this->spu_decoder_class.get_identifier = dxr3_spudec_get_identifier; - this->spu_decoder_class.get_description = dxr3_spudec_get_description; - this->spu_decoder_class.dispose = dxr3_spudec_class_dispose; + this->spu_decoder_class.identifier = "dxr3-spudec"; + this->spu_decoder_class.description = N_("subtitle decoder plugin using the hardware decoding capabilities of a DXR3 decoder card"); + this->spu_decoder_class.dispose = default_spu_decoder_class_dispose; this->instance = 0; @@ -286,22 +265,6 @@ static spu_decoder_t *dxr3_spudec_open_plugin(spu_decoder_class_t *class_gen, xi return &this->spu_decoder; } -static char *dxr3_spudec_get_identifier(spu_decoder_class_t *class_gen) -{ - return "dxr3-spudec"; -} - -static char *dxr3_spudec_get_description(spu_decoder_class_t *class_gen) -{ - return "subtitle decoder plugin using the hardware decoding capabilities of a DXR3 decoder card"; -} - -static void dxr3_spudec_class_dispose(spu_decoder_class_t *class_gen) -{ - free(class_gen); -} - - static void dxr3_spudec_decode_data(spu_decoder_t *this_gen, buf_element_t *buf) { dxr3_spudec_t *this = (dxr3_spudec_t *)this_gen; @@ -582,7 +545,7 @@ static void dxr3_spudec_discontinuity(spu_decoder_t *this_gen) static void dxr3_spudec_dispose(spu_decoder_t *this_gen) { - uint8_t empty_spu[] = { + static const uint8_t empty_spu[] = { 0x00, 0x26, 0x00, 0x08, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x20, 0x01, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x01, 0x00, diff --git a/src/dxr3/dxr3_decode_video.c b/src/dxr3/dxr3_decode_video.c index 71c6b4d1b..ec28b4648 100644 --- a/src/dxr3/dxr3_decode_video.c +++ b/src/dxr3/dxr3_decode_video.c @@ -44,8 +44,8 @@ #define LOG_VID 0 #define LOG_PTS 0 -#include "xine_internal.h" -#include "buffer.h" +#include <xine/xine_internal.h> +#include <xine/buffer.h> #include "video_out_dxr3.h" #include "dxr3.h" @@ -71,7 +71,7 @@ static void *dxr3_init_plugin(xine_t *xine, void *); /* plugin catalog information */ -static uint32_t supported_types[] = { BUF_VIDEO_MPEG, 0 }; +static const uint32_t supported_types[] = { BUF_VIDEO_MPEG, 0 }; static const decoder_info_t dxr3_video_decoder_info = { supported_types, /* supported types */ @@ -80,16 +80,13 @@ static const decoder_info_t dxr3_video_decoder_info = { const plugin_info_t xine_plugin_info[] EXPORTED = { /* type, API, "name", version, special_info, init_function */ - { PLUGIN_VIDEO_DECODER, 18, "dxr3-mpeg2", XINE_VERSION_CODE, &dxr3_video_decoder_info, &dxr3_init_plugin }, + { PLUGIN_VIDEO_DECODER, 19, "dxr3-mpeg2", XINE_VERSION_CODE, &dxr3_video_decoder_info, &dxr3_init_plugin }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; /* plugin class functions */ static video_decoder_t *dxr3_open_plugin(video_decoder_class_t *class_gen, xine_stream_t *stream); -static char *dxr3_get_identifier(video_decoder_class_t *class_gen); -static char *dxr3_get_description(video_decoder_class_t *class_gen); -static void dxr3_class_dispose(video_decoder_class_t *class_gen); /* plugin instance functions */ static void dxr3_decode_data(video_decoder_t *this_gen, buf_element_t *buf); @@ -152,7 +149,6 @@ typedef struct dxr3_decoder_s { } dxr3_decoder_t; /* helper functions */ -static inline int dxr3_present(xine_stream_t *stream); static inline int dxr3_mvcommand(int fd_control, int command); static void parse_mpeg_header(dxr3_decoder_t *this, uint8_t *buffer); static int get_duration(dxr3_decoder_t *this); @@ -165,24 +161,6 @@ static void dxr3_update_enhanced_mode(void *this_gen, xine_cfg_entry_t *ent static void dxr3_update_correct_durations(void *this_gen, xine_cfg_entry_t *entry); /* inline helper implementations */ -static inline int dxr3_present(xine_stream_t *stream) -{ - plugin_node_t *node; - video_driver_class_t *vo_class; - int present = 0; - - if (stream->video_driver && stream->video_driver->node) { - node = (plugin_node_t *)stream->video_driver->node; - if (node->plugin_class) { - vo_class = (video_driver_class_t *)node->plugin_class; - if (vo_class->get_identifier) - present = (strcmp(vo_class->get_identifier(vo_class), DXR3_VO_ID) == 0); - } - } - llprintf(LOG_VID, "dxr3 %s\n", present ? "present" : "not present"); - return present; -} - static inline int dxr3_mvcommand(int fd_control, int command) { em8300_register_t reg; @@ -203,9 +181,9 @@ static void *dxr3_init_plugin(xine_t *xine, void *data) if (!this) return NULL; this->video_decoder_class.open_plugin = dxr3_open_plugin; - this->video_decoder_class.get_identifier = dxr3_get_identifier; - this->video_decoder_class.get_description = dxr3_get_description; - this->video_decoder_class.dispose = dxr3_class_dispose; + this->video_decoder_class.identifier = "dxr3-mpeg2"; + this->video_decoder_class.description = N_("MPEGI/II decoder plugin using the hardware decoding capabilities of a DXR3 decoder card."); + this->video_decoder_class.dispose = default_video_decoder_class_dispose; this->instance = 0; @@ -217,7 +195,7 @@ static void *dxr3_init_plugin(xine_t *xine, void *data) static video_decoder_t *dxr3_open_plugin(video_decoder_class_t *class_gen, xine_stream_t *stream) { - static char *panscan_types[] = { "only when forced", "use MPEG hint", "use DVB hint", NULL }; + static const char *const panscan_types[] = { "only when forced", "use MPEG hint", "use DVB hint", NULL }; dxr3_decoder_t *this; dxr3_decoder_class_t *class = (dxr3_decoder_class_t *)class_gen; config_values_t *cfg; @@ -305,22 +283,6 @@ static video_decoder_t *dxr3_open_plugin(video_decoder_class_t *class_gen, xine_ return &this->video_decoder; } -static char *dxr3_get_identifier(video_decoder_class_t *class_gen) -{ - return "dxr3-mpeg2"; -} - -static char *dxr3_get_description(video_decoder_class_t *class_gen) -{ - return "MPEGI/II decoder plugin using the hardware decoding capabilities of a DXR3 decoder card."; -} - -static void dxr3_class_dispose(video_decoder_class_t *class_gen) -{ - free(class_gen); -} - - static void dxr3_decode_data(video_decoder_t *this_gen, buf_element_t *buf) { dxr3_decoder_t *this = (dxr3_decoder_t *)this_gen; @@ -650,7 +612,7 @@ static void dxr3_flush(video_decoder_t *this_gen) * (the highlights won't move without), but some dvds have stills * with no sequence end code. Since it is very likely that flush() is called * in still situations, we send one here. */ - static uint8_t end_buffer[4] = { 0x00, 0x00, 0x01, 0xb7 }; + static const uint8_t end_buffer[4] = { 0x00, 0x00, 0x01, 0xb7 }; write(this->fd_video, &end_buffer, 4); this->sequence_open = 0; xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "dxr3_decode_video: WARNING: added missing end sequence\n"); diff --git a/src/dxr3/dxr3_mpeg_encoders.c b/src/dxr3/dxr3_mpeg_encoders.c index 8ca48c6ae..7e9a0e523 100644 --- a/src/dxr3/dxr3_mpeg_encoders.c +++ b/src/dxr3/dxr3_mpeg_encoders.c @@ -44,11 +44,17 @@ #include <math.h> #include <unistd.h> +#ifdef HAVE_FFMPEG_AVUTIL_H +# include <mem.h> +#else +# include <libavutil/mem.h> +#endif + #define LOG_MODULE "dxr3_mpeg_encoder" /* #define LOG_VERBOSE */ /* #define LOG */ -#include "xineutils.h" +#include <xine/xineutils.h> #include "video_out_dxr3.h" /* buffer size for encoded mpeg1 stream; will hold one intra frame @@ -99,7 +105,7 @@ typedef struct { char *buffer; /* temporary buffer for mpeg data */ /* temporary buffer for YUY2->YV12 conversion */ uint8_t *out[3]; /* aligned buffer for YV12 data */ - uint8_t *buf; /* unaligned YV12 buffer */ + uint8_t *buf; /* base address of YV12 buffer */ } fame_data_t; /* helper function */ @@ -107,13 +113,6 @@ static int fame_prepare_frame(fame_data_t *this, dxr3_driver_t *drv, dxr3_frame_t *frame); #endif -/* initialization function */ -int dxr3_lavc_init(dxr3_driver_t *drv, plugin_node_t *node); - -/* close function from encoder api */ -static int lavc_on_close(dxr3_driver_t *drv); - - #ifdef HAVE_LIBRTE int dxr3_rte_init(dxr3_driver_t *drv) { @@ -337,8 +336,7 @@ static int fame_on_update_format(dxr3_driver_t *drv, dxr3_frame_t *frame) fame_parameters_t init_fp = FAME_PARAMETERS_INITIALIZER; double fps; - if (this->buf) free(this->buf); - this->buf = 0; + av_freep(&this->buf); this->out[0] = this->out[1] = this->out[2] = 0; /* if YUY2 and dimensions changed, we need to re-allocate the @@ -346,8 +344,7 @@ static int fame_on_update_format(dxr3_driver_t *drv, dxr3_frame_t *frame) if (frame->vo_frame.format == XINE_IMGFMT_YUY2) { int image_size = frame->vo_frame.width * frame->oheight; - this->out[0] = xine_xmalloc_aligned(16, image_size * 3/2, - (void *)&this->buf); + this->out[0] = this->buf = av_mallocz(image_size * 3/2); this->out[1] = this->out[0] + image_size; this->out[2] = this->out[1] + image_size/4; @@ -537,33 +534,3 @@ static int fame_prepare_frame(fame_data_t *this, dxr3_driver_t *drv, dxr3_frame_ return 1; } #endif - - -int dxr3_lavc_init(dxr3_driver_t *drv, plugin_node_t *node) -{ - void *ffmpeg; - int (*init)(dxr3_driver_t *); - int result; - - ffmpeg = dlopen(node->file->filename, RTLD_LAZY); - if (!ffmpeg) return 0; - - init = dlsym(ffmpeg, "dxr3_encoder_init"); - if (!init) return 0; - - result = init(drv); - /* the close function is implemented here, because it will call dlclose() - * and that should not be done be the library we are closing... */ - drv->enc->on_close = lavc_on_close; - drv->enc->handle = ffmpeg; - return result; -} - -static int lavc_on_close(dxr3_driver_t *drv) -{ - drv->enc->on_unneeded(drv); - dlclose(drv->enc->handle); - free(drv->enc); - drv->enc = NULL; - return 1; -} diff --git a/src/dxr3/dxr3_scr.h b/src/dxr3/dxr3_scr.h index 612f16ccb..28e2e0f1b 100644 --- a/src/dxr3/dxr3_scr.h +++ b/src/dxr3/dxr3_scr.h @@ -18,7 +18,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA */ -#include "xine_internal.h" +#include <xine/xine_internal.h> /* plugin structure */ diff --git a/src/dxr3/ffmpeg_encoder.c b/src/dxr3/ffmpeg_encoder.c new file mode 100644 index 000000000..4b444a3bc --- /dev/null +++ b/src/dxr3/ffmpeg_encoder.c @@ -0,0 +1,339 @@ +/* + * Copyright (C) 2000-2004 the xine project + * + * This file is part of xine, a unix video player. + * + * xine 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. + * + * xine 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 02110, USA + */ + +/* mpeg encoders for the dxr3 video out plugin. */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <sys/ioctl.h> +#include <fcntl.h> +#include <unistd.h> +#include <errno.h> +#include <math.h> + +#define LOG_MODULE "dxr3_mpeg_encoder" +/* #define LOG_VERBOSE */ +/* #define LOG */ + +#include "video_out_dxr3.h" + +#ifdef HAVE_FFMPEG_AVUTIL_H +# include <avcodec.h> +#else +# include <libavcodec/avcodec.h> +#endif + +#include "../combined/ffmpeg/ffmpeg_compat.h" + +/* buffer size for encoded mpeg1 stream; will hold one intra frame + * at 640x480 typical sizes are <50 kB. 512 kB should be plenty */ +#define DEFAULT_BUFFER_SIZE 512*1024 + + +/* functions required by encoder api */ +static int lavc_on_update_format(dxr3_driver_t *drv, dxr3_frame_t *frame); +static int lavc_on_display_frame(dxr3_driver_t *drv, dxr3_frame_t *frame); +static int lavc_on_unneeded(dxr3_driver_t *drv); + +/*encoder structure*/ +typedef struct lavc_data_s { + encoder_data_t encoder_data; + AVCodecContext *context; /* handle for encoding */ + int width, height; /* width and height of the video frame */ + uint8_t *ffmpeg_buffer; /* lavc buffer */ + AVFrame *picture; /* picture to be encoded */ + uint8_t *out[3]; /* aligned buffer for YV12 data */ + uint8_t *buf; /* base address of YV12 buffer */ +} lavc_data_t; + + +static int dxr3_lavc_close(dxr3_driver_t *drv) { + drv->enc->on_unneeded(drv); + free(drv->enc); + drv->enc = NULL; + + return 1; +} + +int dxr3_lavc_init(dxr3_driver_t *drv, plugin_node_t *plugin) +{ + lavc_data_t* this; + avcodec_init(); + + avcodec_register_all(); + lprintf("lavc init , version %x\n", avcodec_version()); + this = calloc(1, sizeof(lavc_data_t)); + if (!this) return 0; + + this->encoder_data.type = ENC_LAVC; + this->encoder_data.on_update_format = lavc_on_update_format; + this->encoder_data.on_frame_copy = NULL; + this->encoder_data.on_display_frame = lavc_on_display_frame; + this->encoder_data.on_unneeded = lavc_on_unneeded; + this->context = 0; + + drv->enc = &this->encoder_data; + drv->enc->on_close = dxr3_lavc_close; + return 1; +} + +/* helper function */ +static int lavc_prepare_frame(lavc_data_t *this, dxr3_driver_t *drv, dxr3_frame_t *frame); + +static int lavc_on_update_format(dxr3_driver_t *drv, dxr3_frame_t *frame) +{ + lavc_data_t *this = (lavc_data_t *)drv->enc; + AVCodec *codec; + unsigned char use_quantizer; + + if (this->context) { + avcodec_close(this->context); + free(this->context); + free(this->picture); + this->context = NULL; + this->picture = NULL; + } + + /* if YUY2 and dimensions changed, we need to re-allocate the + * internal YV12 buffer */ + if (frame->vo_frame.format == XINE_IMGFMT_YUY2) { + int image_size = frame->vo_frame.pitches[0] * frame->oheight; + + this->out[0] = this->buf = av_mallocz(image_size * 3/2); + this->out[1] = this->out[0] + image_size; + this->out[2] = this->out[1] + image_size/4; + + /* fill with black (yuv 16,128,128) */ + memset(this->out[0], 16, image_size); + memset(this->out[1], 128, image_size/4); + memset(this->out[2], 128, image_size/4); + lprintf("Using YUY2->YV12 conversion\n"); + } + + /* resolution must be a multiple of two */ + if ((frame->vo_frame.pitches[0] % 2 != 0) || (frame->oheight % 2 != 0)) { + xprintf(drv->class->xine, XINE_VERBOSITY_LOG, + "dxr3_mpeg_encoder: lavc only handles video dimensions which are multiples of 2\n"); + return 0; + } + + /* get mpeg codec handle */ + codec = avcodec_find_encoder(CODEC_ID_MPEG1VIDEO); + if (!codec) { + xprintf(drv->class->xine, XINE_VERBOSITY_LOG, + "dxr3_mpeg_encoder: lavc MPEG1 codec not found\n"); + return 0; + } + lprintf("lavc MPEG1 encoder found.\n"); + + this->width = frame->vo_frame.pitches[0]; + this->height = frame->oheight; + + this->context = avcodec_alloc_context(); + if (!this->context) { + xprintf(drv->class->xine, XINE_VERBOSITY_LOG, + "dxr3_mpeg_encoder: Couldn't start the ffmpeg library\n"); + return 0; + } + this->picture = avcodec_alloc_frame(); + if (!this->picture) { + xprintf(drv->class->xine, XINE_VERBOSITY_LOG, + "dxr3_mpeg_encoder: Couldn't allocate ffmpeg frame\n"); + return 0; + } + + /* mpeg1 encoder only support YUV420P */ + this->context->pix_fmt = PIX_FMT_YUVJ420P; + + /* put sample parameters */ + this->context->bit_rate = drv->class->xine->config->register_range(drv->class->xine->config, + "dxr3.encoding.lavc_bitrate", 10000, 1000, 20000, + _("libavcodec mpeg output bitrate (kbit/s)"), + _("The bitrate the libavcodec mpeg encoder should use for DXR3's encoding mode. " + "Higher values will increase quality and CPU usage.\n" + "This setting is only considered, when constant quality mode is disabled."), 10, NULL, NULL); + this->context->bit_rate *= 1000; /* config in kbit/s, libavcodec wants bit/s */ + + use_quantizer = drv->class->xine->config->register_bool(drv->class->xine->config, + "dxr3.encoding.lavc_quantizer", 1, + _("constant quality mode"), + _("When enabled, libavcodec will use a constant quality mode by dynamically " + "compressing the images based on their complexity. When disabled, libavcodec " + "will use constant bitrate mode."), 10, NULL, NULL); + + if (use_quantizer) { + this->context->qmin = drv->class->xine->config->register_range(drv->class->xine->config, + "dxr3.encoding.lavc_qmin", 1, 1, 10, + _("minimum compression"), + _("The minimum compression to apply to an image in constant quality mode."), + 10, NULL, NULL); + + this->context->qmax = drv->class->xine->config->register_range(drv->class->xine->config, + "dxr3.encoding.lavc_qmax", 2, 1, 20, + _("maximum quantizer"), + _("The maximum compression to apply to an image in constant quality mode."), + 10, NULL, NULL); + } + + lprintf("lavc -> bitrate %d \n", this->context->bit_rate); + + this->context->width = frame->vo_frame.pitches[0]; + this->context->height = frame->oheight; + + this->context->gop_size = 0; /*intra frames only */ + this->context->me_method = ME_ZERO; /*motion estimation type*/ + + this->context->time_base.den = 90000; + if (frame->vo_frame.duration > 90000 / 24) + this->context->time_base.num = 90000 / 24; + else if (frame->vo_frame.duration < 90000 / 60) + this->context->time_base.num = 90000 / 60; + else + this->context->time_base.num = frame->vo_frame.duration; + /* ffmpeg can complain about illegal framerates, but since this seems no + * problem for the DXR3, we just tell ffmpeg to be more lax with */ + this->context->strict_std_compliance = -1; + + /* open avcodec */ + if (avcodec_open(this->context, codec) < 0) { + xprintf(drv->class->xine, XINE_VERBOSITY_LOG, "dxr3_mpeg_encoder: could not open codec\n"); + return 0; + } + lprintf("dxr3_mpeg_encoder: lavc MPEG1 codec opened.\n"); + + if (!this->ffmpeg_buffer) + this->ffmpeg_buffer = (unsigned char *)malloc(DEFAULT_BUFFER_SIZE); /* why allocate more than needed ?! */ + if (!this->ffmpeg_buffer) { + xprintf(drv->class->xine, XINE_VERBOSITY_LOG, + "dxr3_mpeg_encoder: Couldn't allocate temp buffer for mpeg data\n"); + return 0; + } + + return 1; +} + +static int lavc_on_display_frame(dxr3_driver_t *drv, dxr3_frame_t *frame) +{ + int size; + lavc_data_t* this = (lavc_data_t *)drv->enc; + ssize_t written; + + if (frame->vo_frame.bad_frame) return 1; + /* ignore old frames */ + if ((frame->vo_frame.pitches[0] != this->context->width) || (frame->oheight != this->context->height)) { + frame->vo_frame.free(&frame->vo_frame); + lprintf("LAVC ignoring frame !!!\n"); + return 1; + } + + /* prepare frame for conversion, handles YUY2 -> YV12 conversion when necessary */ + lavc_prepare_frame(this, drv, frame); + + /* do the encoding */ + size = avcodec_encode_video(this->context, this->ffmpeg_buffer, DEFAULT_BUFFER_SIZE, this->picture); + + frame->vo_frame.free(&frame->vo_frame); + + if (size < 0) { + xprintf(drv->class->xine, XINE_VERBOSITY_LOG, + "dxr3_mpeg_encoder: encoding failed\n"); + return 0; + } + + written = write(drv->fd_video, this->ffmpeg_buffer, size); + if (written < 0) { + xprintf(drv->class->xine, XINE_VERBOSITY_LOG, + "dxr3_mpeg_encoder: video device write failed (%s)\n", strerror(errno)); + return 0; + } + if (written != size) + xprintf(drv->class->xine, XINE_VERBOSITY_LOG, + "dxr3_mpeg_encoder: Could only write %zd of %d mpeg bytes.\n", written, size); + return 1; +} + +static int lavc_on_unneeded(dxr3_driver_t *drv) +{ + lavc_data_t *this = (lavc_data_t *)drv->enc; + lprintf("flushing buffers\n"); + if (this->context) { + avcodec_close(this->context); + free(this->context); + free(this->picture); + this->context = NULL; + this->picture = NULL; + } + return 1; +} + +static int lavc_prepare_frame(lavc_data_t *this, dxr3_driver_t *drv, dxr3_frame_t *frame) +{ + int i, j, w2; + uint8_t *yuy2; + + if (frame->vo_frame.bad_frame) return 1; + + if (frame->vo_frame.format == XINE_IMGFMT_YUY2) { + /* need YUY2->YV12 conversion */ + if (!(this->out[0] && this->out[1] && this->out[2]) ) { + lprintf("Internal YV12 buffer not created.\n"); + return 0; + } + this->picture->data[0] = this->out[0] + frame->vo_frame.pitches[0] * drv->top_bar; /* y */ + this->picture->data[1] = this->out[1] + (frame->vo_frame.pitches[0] / 2) * (drv->top_bar / 2); /* u */ + this->picture->data[2] = this->out[2] + (frame->vo_frame.pitches[0] / 2) * (drv->top_bar / 2); /* v */ + yuy2 = frame->vo_frame.base[0]; + w2 = frame->vo_frame.pitches[0] / 2; + for (i = 0; i < frame->vo_frame.height; i += 2) { + for (j = 0; j < w2; j++) { + /* packed YUV 422 is: Y[i] U[i] Y[i+1] V[i] */ + *(this->picture->data[0]++) = *(yuy2++); + *(this->picture->data[1]++) = *(yuy2++); + *(this->picture->data[0]++) = *(yuy2++); + *(this->picture->data[2]++) = *(yuy2++); + } + /* down sampling */ + for (j = 0; j < w2; j++) { + /* skip every second line for U and V */ + *(this->picture->data[0]++) = *(yuy2++); + yuy2++; + *(this->picture->data[0]++) = *(yuy2++); + yuy2++; + } + } + /* reset for encoder */ + this->picture->data[0] = this->out[0]; + this->picture->data[1] = this->out[1]; + this->picture->data[2] = this->out[2]; + } + else { /* YV12 **/ + this->picture->data[0] = frame->real_base[0]; + this->picture->data[1] = frame->real_base[1]; + this->picture->data[2] = frame->real_base[2]; + } + this->picture->linesize[0] = this->context->width; + this->picture->linesize[1] = this->context->width / 2; + this->picture->linesize[2] = this->context->width / 2; + return 1; +} diff --git a/src/dxr3/video_out_dxr3.c b/src/dxr3/video_out_dxr3.c index ed5ae4b58..1fd1028a8 100644 --- a/src/dxr3/video_out_dxr3.c +++ b/src/dxr3/video_out_dxr3.c @@ -60,12 +60,18 @@ #define LOG_VID 0 #define LOG_OVR 0 -#include "xine_internal.h" -#include "xineutils.h" -#include "video_out.h" +#include <xine/xine_internal.h> +#include <xine/xineutils.h> +#include <xine/video_out.h> #include "dxr3.h" #include "video_out_dxr3.h" +#ifdef HAVE_FFMPEG_AVUTIL_H +# include <mem.h> +#else +# include <libavutil/mem.h> +#endif + #include "compat.c" /* the amount of extra time we give the card for decoding */ @@ -94,17 +100,15 @@ static const vo_info_t vo_info_dxr3_aa = { const plugin_info_t xine_plugin_info[] EXPORTED = { /* type, API, "name", version, special_info, init_function */ #ifdef HAVE_X11 - { PLUGIN_VIDEO_OUT, 21, "dxr3", XINE_VERSION_CODE, &vo_info_dxr3_x11, &dxr3_x11_init_plugin }, + { PLUGIN_VIDEO_OUT, 22, "dxr3", XINE_VERSION_CODE, &vo_info_dxr3_x11, &dxr3_x11_init_plugin }, #endif - { PLUGIN_VIDEO_OUT, 21, "aadxr3", XINE_VERSION_CODE, &vo_info_dxr3_aa, &dxr3_aa_init_plugin }, + { PLUGIN_VIDEO_OUT, 22, "aadxr3", XINE_VERSION_CODE, &vo_info_dxr3_aa, &dxr3_aa_init_plugin }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; /* plugin class functions */ static vo_driver_t *dxr3_vo_open_plugin(video_driver_class_t *class_gen, const void *visual); -static char *dxr3_vo_get_identifier(video_driver_class_t *class_gen); -static char *dxr3_vo_get_description(video_driver_class_t *class_gen); static void dxr3_vo_class_dispose(video_driver_class_t *class_gen); /* plugin instance functions */ @@ -178,8 +182,8 @@ static dxr3_driver_class_t *dxr3_vo_init_plugin(xine_t *xine, void *visual_gen) CONF_KEY, 0, CONF_NAME, CONF_HELP, 10, NULL, NULL); this->video_driver_class.open_plugin = dxr3_vo_open_plugin; - this->video_driver_class.get_identifier = dxr3_vo_get_identifier; - this->video_driver_class.get_description = dxr3_vo_get_description; + this->video_driver_class.identifier = DXR3_VO_ID; + this->video_driver_class.description = N_("video output plugin displaying images through your DXR3 decoder card"); this->video_driver_class.dispose = dxr3_vo_class_dispose; this->xine = xine; @@ -191,16 +195,6 @@ static dxr3_driver_class_t *dxr3_vo_init_plugin(xine_t *xine, void *visual_gen) return this; } -static char *dxr3_vo_get_identifier(video_driver_class_t *class_gen) -{ - return DXR3_VO_ID; -} - -static char *dxr3_vo_get_description(video_driver_class_t *class_gen) -{ - return "video output plugin displaying images through your DXR3 decoder card"; -} - static void dxr3_vo_class_dispose(video_driver_class_t *class_gen) { dxr3_driver_class_t *class = (dxr3_driver_class_t *)class_gen; @@ -222,13 +216,14 @@ static vo_driver_t *dxr3_vo_open_plugin(video_driver_class_t *class_gen, const v static char *available_encoders[SUPPORTED_ENCODER_COUNT + 2]; plugin_node_t *node; + static const char *const videoout_modes[] = { + "letterboxed tv", "widescreen tv", #ifdef HAVE_X11 - static const char const *videoout_modes[] = { "letterboxed tv", "widescreen tv", - "letterboxed overlay", "widescreen overlay", NULL }; -#else - static const char const *videoout_modes[] = { "letterboxed tv", "widescreen tv", NULL }; + "letterboxed overlay", "widescreen overlay", #endif - static const char const *tv_modes[] = { "ntsc", "pal", "pal60" , "default", NULL }; + NULL + }; + static const char *const tv_modes[] = { "ntsc", "pal", "pal60" , "default", NULL }; int list_id, list_size; xine_sarray_t *plugin_list; @@ -299,21 +294,8 @@ static vo_driver_t *dxr3_vo_open_plugin(video_driver_class_t *class_gen, const v #if LOG_VID printf("video_out_dxr3: Supported mpeg encoders: "); #endif - /* check, if ffmpeg plugin is available by looking through plugin - * catalog; catalog mutex is already locked here, since this is open_plugin() */ - node = NULL; - plugin_list = class->xine->plugin_catalog->plugin_lists[PLUGIN_VIDEO_DECODER - 1]; - list_size = xine_sarray_size(plugin_list); - for (list_id = 0; list_id < list_size; list_id++) { - node = xine_sarray_get (plugin_list, list_id); - if (strcasecmp(node->info->id, "ffmpegvideo") == 0) { - available_encoders[encoder++] = "libavcodec"; -#if LOG_VID - printf("libavcodec, "); -#endif - break; - } - } + available_encoders[encoder++] = "libavcodec"; + printf("libavcodec, "); #ifdef HAVE_LIBFAME available_encoders[encoder++] = "fame"; #if LOG_VID @@ -589,7 +571,7 @@ static void dxr3_frame_dispose(vo_frame_t *frame_gen) { dxr3_frame_t *frame = (dxr3_frame_t *)frame_gen; - if (frame->mem) free(frame->mem); + av_free(frame->mem); pthread_mutex_destroy(&frame_gen->mutex); free(frame); } @@ -629,12 +611,9 @@ static void dxr3_update_frame_format(vo_driver_t *this_gen, vo_frame_t *frame_ge frame->aspect = XINE_VO_ASPECT_ANAMORPHIC; frame->pan_scan = flags & VO_PAN_SCAN_FLAG; - if (frame->mem) { - free(frame->mem); - frame->mem = NULL; - frame->real_base[0] = frame->real_base[1] = frame->real_base[2] = NULL; - frame_gen->base[0] = frame_gen->base[1] = frame_gen->base[2] = NULL; - } + av_freep(&frame->mem); + frame->real_base[0] = frame->real_base[1] = frame->real_base[2] = NULL; + frame_gen->base[0] = frame_gen->base[1] = frame_gen->base[2] = NULL; return; } @@ -719,10 +698,7 @@ static void dxr3_update_frame_format(vo_driver_t *this_gen, vo_frame_t *frame_ge /* if dimensions changed, we need to re-allocate frame memory */ if ((frame->vo_frame.width != width) || (frame->vo_frame.height != height) || (frame->oheight != oheight) || (frame->vo_frame.format != format)) { - if (frame->mem) { - free (frame->mem); - frame->mem = NULL; - } + av_freep(&frame->mem); if (format == XINE_IMGFMT_YUY2) { int i, image_size; @@ -733,8 +709,7 @@ static void dxr3_update_frame_format(vo_driver_t *this_gen, vo_frame_t *frame_ge /* planar format, only base[0] */ /* add one extra line for field swap stuff */ - frame->real_base[0] = xine_xmalloc_aligned(16, image_size + frame->vo_frame.pitches[0], - &frame->mem); + frame->real_base[0] = frame->mem = av_mallocz(image_size + frame->vo_frame.pitches[0]); /* don't use first line */ frame->real_base[0] += frame->vo_frame.pitches[0]; @@ -761,8 +736,8 @@ static void dxr3_update_frame_format(vo_driver_t *this_gen, vo_frame_t *frame_ge image_size_v = frame->vo_frame.pitches[2] * ((oheight + 1) / 2); /* add one extra line for field swap stuff */ - frame->real_base[0] = xine_xmalloc_aligned(16, image_size_y + frame->vo_frame.pitches[0] + - image_size_u + image_size_v, &frame->mem); + frame->real_base[0] = frame->mem = av_mallocz(image_size_y + frame->vo_frame.pitches[0] + + image_size_u + image_size_v); /* don't use first line */ frame->real_base[0] += frame->vo_frame.pitches[0]; diff --git a/src/dxr3/video_out_dxr3.h b/src/dxr3/video_out_dxr3.h index 7e24781bf..8158bba8e 100644 --- a/src/dxr3/video_out_dxr3.h +++ b/src/dxr3/video_out_dxr3.h @@ -26,8 +26,8 @@ # include <X11/Xlib.h> #endif -#include "xine_internal.h" -#include "vo_scale.h" +#include <xine/xine_internal.h> +#include <xine/vo_scale.h> #include "dxr3_scr.h" #include "dxr3.h" |