summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/dxr3/Makefile.am15
-rw-r--r--src/dxr3/dxr3_video_out.h47
-rw-r--r--src/dxr3/dxr3_vo_encoder.c950
-rw-r--r--src/dxr3/dxr3_vo_encoder.h89
-rw-r--r--src/dxr3/dxr3_vo_standard.c43
5 files changed, 602 insertions, 542 deletions
diff --git a/src/dxr3/Makefile.am b/src/dxr3/Makefile.am
index 163846a4f..d9f73e932 100644
--- a/src/dxr3/Makefile.am
+++ b/src/dxr3/Makefile.am
@@ -6,15 +6,18 @@ LIBTOOL = $(SHELL) $(top_builddir)/libtool-nofpic
libdir = $(XINE_PLUGINDIR)
-# replace -lfame by -lrte below and define USE_MP1E 1 in dxr3_vo_decoder.h to
-# use librte! Works with API of librte-0.4.
-
if HAVE_DXR3
-if HAVE_FAME
+if HAVE_ENCODER
dxr3enc_module = xineplug_vo_out_dxr3enc.la
endif
dxr3_modules = xineplug_decode_dxr3.la xineplug_vo_out_dxr3.la
endif
+if HAVE_LIBFAME
+link_fame=-lfame
+endif
+if HAVE_LIBRTE
+link_rte=-lrte
+endif
lib_LTLIBRARIES = $(dxr3_modules) $(dxr3enc_module)
@@ -26,9 +29,9 @@ xineplug_vo_out_dxr3_la_LDFLAGS = -avoid-version -module $(X_LIBS)
xineplug_vo_out_dxr3enc_la_SOURCES = dxr3_vo_encoder.c dxr3_vo_core.c
xineplug_vo_out_dxr3enc_la_LDFLAGS = \
- -avoid-version -module -lfame $(X_LIBS)
+ -avoid-version -module $(link_fame) $(link_rte) $(X_LIBS)
-include_HEADERS = dxr3_video_out.h dxr3_vo_encoder.h
+include_HEADERS = dxr3_video_out.h
debug:
@$(MAKE) CFLAGS="$(DEBUG_CFLAGS) $(LINUX_INCLUDE)"
diff --git a/src/dxr3/dxr3_video_out.h b/src/dxr3/dxr3_video_out.h
index 9a956e2f3..bf9174fe8 100644
--- a/src/dxr3/dxr3_video_out.h
+++ b/src/dxr3/dxr3_video_out.h
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
- * $Id: dxr3_video_out.h,v 1.8 2001/11/29 07:17:07 mlampard Exp $
+ * $Id: dxr3_video_out.h,v 1.9 2001/12/11 02:26:59 hrm Exp $
*
*/
@@ -80,6 +80,9 @@ typedef struct {
struct coeff colcal_lower[3];
} dxr3_overlay_t;
+typedef enum { ENC_FAME, ENC_RTE } encoder_type;
+typedef struct encoder_data_s encoder_data_t;
+
typedef struct dxr3_driver_s {
vo_driver_t vo_driver;
config_values_t *config;
@@ -87,14 +90,21 @@ typedef struct dxr3_driver_s {
int fd_video;
int aspectratio;
int tv_mode;
+ int enhanced_mode; /* enhanced play mode */
em8300_bcs_t bcs;
-
+ const char *devname;
+
/* for encoder plugin */
- uint8_t *out[3]; /* aligned buffer for YV12 data, copied from frames */
- uint8_t *buf[3]; /* unaligned YV12 buffer */
- int oheight; /* height after adding black bars to correct a.r. */
- int video_iheight; /* input height (before adding black bars) */
- int video_height; /* output height (after adding bars) */
+ encoder_data_t *enc; /* encoder data */
+ double fps; /* frames per second */
+ int format; /* color format */
+ const char *file_out;
+ /* height after adding black bars to correct a.r. */
+ int oheight;
+ /* input height (before adding black bars) */
+ int video_iheight;
+ /* output height (after adding bars) */
+ int video_height;
/* for overlay */
dxr3_overlay_t overlay;
@@ -116,25 +126,30 @@ typedef struct dxr3_driver_s {
char *user_data;
- void (*request_dest_size) (char *userdata, int video_width, int video_height, int *dest_x,
+ void (*request_dest_size) (char *userdata, int video_width,
+ int video_height, int *dest_x,
int *dest_y, int *dest_height, int *dest_width);
} dxr3_driver_t;
typedef struct dxr3_frame_s {
vo_frame_t vo_frame;
- int width, height;
- uint8_t *mem[3]; /* allocated for YV12 or YUY2 buffers */
- uint8_t *real_base[3]; /* same buffers alligned on 16 bytes */
+ int width, height,oheight;
+ uint8_t *mem; /* allocated for YV12 or YUY2 buffers */
+ uint8_t *real_base[3]; /* yuv/yuy2 buffers in mem aligned on 16 */
int format;
dxr3_driver_t *vo_instance; /* points to self, for use in dxr3_frame_copy */
int copy_calls; /* counts calls to dxr3_frame_copy function */
-#if USE_MPEG_BUFFER
unsigned char *mpeg; /* encoded mpeg data */
unsigned int mpeg_size; /* length of data */
-#endif
-}dxr3_frame_t;
-
-static char *devname;
+} dxr3_frame_t;
+
+struct encoder_data_s {
+ encoder_type type;
+ int (*on_update_format)(dxr3_driver_t *);
+ int (*on_frame_copy)(dxr3_driver_t *, dxr3_frame_t *, uint8_t **src);
+ int (*on_display_frame)(dxr3_driver_t *, dxr3_frame_t *);
+ int (*on_close)(dxr3_driver_t *);
+};
/* func definitions */
/* Overlay functions */
diff --git a/src/dxr3/dxr3_vo_encoder.c b/src/dxr3/dxr3_vo_encoder.c
index 37db0f1c7..368c03e88 100644
--- a/src/dxr3/dxr3_vo_encoder.c
+++ b/src/dxr3/dxr3_vo_encoder.c
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
- * $Id: dxr3_vo_encoder.c,v 1.12 2001/12/02 21:14:51 hrm Exp $
+ * $Id: dxr3_vo_encoder.c,v 1.13 2001/12/11 02:26:59 hrm Exp $
*
* mpeg1 encoding video out plugin for the dxr3.
*
@@ -131,41 +131,85 @@
* API is still under development so don't expect newer versions to work
* right away), define USE_MP1E 1 in the header below and change -lfame
* to -lrte in Makefile.am
+ *
+ ****** Update 11/12/2001 by Harm
+ *
+ * Much much needed clean up.
+ * Dropped ffmpeg support for the moment. Moved almost all libfame and
+ * librte stuff in separate sections, defined general encoder API
+ * in encoder_data_t.
+ *
*/
-/* encoder specific config/setup stuff *
- * must be before dxr3_video_out.h */
-#include "dxr3_vo_encoder.h"
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#ifdef HAVE_LIBRTE
+# define _GNU_SOURCE
+# include <unistd.h>
+# include <rte.h>
+#endif
+#ifdef HAVE_LIBFAME
+# include <fame.h>
+#endif
-/* dxr3 vo globals */
#include "dxr3_video_out.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
+
+#ifdef HAVE_LIBFAME
+typedef struct {
+ encoder_data_t encoder_data;
+ fame_context_t *fc; /* needed for fame calls */
+ fame_parameters_t fp;
+ fame_yuv_t yuv;
+ /* temporary buffer for mpeg data */
+ char *buffer;
+ /* temporary buffer for YUY2->YV12 conversion */
+ uint8_t *out[3]; /* aligned buffer for YV12 data */
+ uint8_t *buf; /* unaligned YV12 buffer */
+} fame_data_t;
+
+int dxr3enc_fame_init(dxr3_driver_t *);
+#endif
+
+#ifdef HAVE_LIBRTE
+typedef struct {
+ encoder_data_t encoder_data;
+ rte_context* context; /* handle for encoding */
+ void* rte_ptr; /* buffer maintened by librte */
+ double rte_time; /* frame time (s) */
+ double rte_time_step; /* time per frame (s) */
+ double rte_bitrate; /* mpeg out bitrate, default 2.3e6 bits/s */
+} rte_data_t;
+
+int dxr3enc_rte_init(dxr3_driver_t *);
+#endif
+
+
+#define MV_COMMAND 0
+
static uint32_t dxr3_get_capabilities (vo_driver_t *this_gen)
{
- /* Since we have no vo format, we return dummy values here */
return VO_CAP_YV12 | VO_CAP_YUY2 |
VO_CAP_SATURATION | VO_CAP_BRIGHTNESS | VO_CAP_CONTRAST;
}
-/* This are dummy functions to fill in the frame object */
-
static void dummy_frame_field (vo_frame_t *vo_img, int which_field)
{
- fprintf(stderr, "dxr3_vo: dummy_frame_field called!\n");
+ /* dummy function */
}
static void dxr3_frame_dispose (vo_frame_t *frame_gen)
{
dxr3_frame_t *frame = (dxr3_frame_t *) frame_gen;
- if (frame->mem[0])
- free (frame->mem[0]);
- if (frame->mem[1])
- free (frame->mem[1]);
- if (frame->mem[2])
- free (frame->mem[2]);
-#if USE_MPEG_BUFFER
- free(frame->mpeg);
-#endif
+ if (frame->mem)
+ free (frame->mem);
+ if (frame->mpeg)
+ free(frame->mpeg);
free(frame);
}
@@ -173,7 +217,6 @@ static void dxr3_frame_copy(vo_frame_t *frame_gen, uint8_t **src);
static vo_frame_t *dxr3_alloc_frame (vo_driver_t *this_gen)
{
- /* dxr3_driver_t *this = (dxr3_driver_t *) this_gen; */
dxr3_frame_t *frame;
frame = (dxr3_frame_t *) malloc (sizeof (dxr3_frame_t));
@@ -183,9 +226,7 @@ static vo_frame_t *dxr3_alloc_frame (vo_driver_t *this_gen)
frame->vo_frame.field = dummy_frame_field;
frame->vo_frame.dispose = dxr3_frame_dispose;
-#if USE_MPEG_BUFFER
frame->mpeg = (unsigned char *) malloc (DEFAULT_BUFFER_SIZE);
-#endif
return (vo_frame_t*) frame;
}
@@ -196,10 +237,9 @@ static void dxr3_update_frame_format (vo_driver_t *this_gen,
int ratio_code, int format, int flags)
{
dxr3_driver_t *this = (dxr3_driver_t *) this_gen;
- int aspect;
+ int aspect,i;
dxr3_frame_t *frame = (dxr3_frame_t *) frame_gen;
int image_size, oheight, top_bar;
- float fps;
/* reset the copy calls counter (number of calls to dxr3_frame_copy) */
frame->copy_calls = 0;
@@ -208,6 +248,8 @@ static void dxr3_update_frame_format (vo_driver_t *this_gen,
aspect = this->aspectratio;
oheight = this->oheight;
+ frame->mpeg_size = 0;
+
/* check aspect ratio, see if we need to add black borders */
if ((this->video_width != width) || (this->video_iheight != height) ||
(this->video_aspect != ratio_code)) {
@@ -239,68 +281,55 @@ static void dxr3_update_frame_format (vo_driver_t *this_gen,
if (oheight - height > 0)
printf("dxr3enc: adding %d black lines to get %s a.r.\n",
oheight-height, aspect == ASPECT_FULL ? "4:3" : "16:9");
-
- /* if YUY2 and dimensions changed, we need to re-allocate the
- * internal YV12 buffer */
- if (format == IMGFMT_YUY2) {
- if (this->buf[0]) free(this->buf[0]);
- if (this->buf[1]) free(this->buf[1]);
- if (this->buf[2]) free(this->buf[2]);
-
- image_size = width * oheight;
-
- this->out[0] = malloc_aligned(16, image_size, (void*)&this->buf[0]);
- this->out[1] = malloc_aligned(16, image_size/4, (void*)&this->buf[1]);
- this->out[2] = malloc_aligned(16, image_size/4, (void*)&this->buf[2]);
-
- /* 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);
-
- printf("dxr3enc: Using YUY2->YV12 conversion\n");
- }
+ this->video_width = width;
+ this->video_iheight = height;
+ this->video_height = oheight;
+ this->video_aspect = ratio_code;
+ this->fps = 90000.0/frame->vo_frame.duration;
+ this->format = format;
+
+ if (this->enc && this->enc->on_update_format)
+ this->enc->on_update_format(this);
}
+
/* if dimensions changed, we need to re-allocate frame memory */
if ((frame->width != width) || (frame->height != height)) {
- if (frame->mem[0]) {
- free (frame->mem[0]);
- frame->mem[0] = NULL;
- }
- if (frame->mem[1]) {
- free (frame->mem[1]);
- frame->mem[1] = NULL;
- }
- if (frame->mem[2]) {
- free (frame->mem[2]);
- frame->mem[2] = NULL;
+ if (frame->mem) {
+ free (frame->mem);
+ frame->mem = NULL;
}
+ /* make top black bar multiple of 16,
+ * so old and new macroblocks overlap */
+ top_bar = ((oheight - height) / 32) * 16;
if (format == IMGFMT_YUY2) {
- image_size = width * height; /* does not include black bars */
+ image_size = width * oheight; /* includes black bars */
/* planar format, only base[0] */
- frame->vo_frame.base[0] = malloc_aligned(16, image_size*2, (void**)&frame->mem[0]);
+ frame->real_base[0] = malloc_aligned(16, image_size*2, (void**)&frame->mem);
+ frame->real_base[1] = frame->real_base[2] = 0;
+
+ /* fix offset, so the decoder does not see the top black bar */
+ frame->vo_frame.base[0] = frame->real_base[0] + width * 2 * top_bar;
frame->vo_frame.base[1] = frame->vo_frame.base[2] = 0;
- frame->real_base[0] = frame->real_base[1] = frame->real_base[2] = 0;
- /* we do the black bar stuff while converting to YV12 */
+
+ /* fill with black (yuy2 16,128,16,128,...) */
+ memset(frame->real_base[0], 128, 2*image_size); /* U and V */
+ for (i=0; i<2*image_size; i+=2)
+ *(frame->vo_frame.base[0]+i) = 16; /* Y */
}
else { /* IMGFMT_YV12 */
image_size = width * oheight; /* includes black bars */
- frame->real_base[0] = malloc_aligned(16,image_size,
- (void**) &frame->mem[0]);
- frame->real_base[1] = malloc_aligned(16,image_size/4,
- (void**) &frame->mem[1]);
- frame->real_base[2] = malloc_aligned(16,image_size/4,
- (void**) &frame->mem[2]);
+ frame->real_base[0] = malloc_aligned(16, image_size * 3/2,
+ (void**) &frame->mem);
+ frame->real_base[1] = frame->real_base[0] + image_size;
+ frame->real_base[2] = frame->real_base[1] + image_size/4;
+
/* fill with black (yuv 16,128,128) */
memset(frame->real_base[0], 16, image_size);
memset(frame->real_base[1], 128, image_size/4);
memset(frame->real_base[2], 128, image_size/4);
- /* make top black bar multiple of 16,
- * so old and new macroblocks overlap */
- top_bar = ((oheight - height) / 16) * 8;
/* fix offsets, so the decoder does not see the top black bar */
frame->vo_frame.base[0] = frame->real_base[0] + width * top_bar;
frame->vo_frame.base[1] = frame->real_base[1] + width * top_bar/4;
@@ -310,343 +339,55 @@ static void dxr3_update_frame_format (vo_driver_t *this_gen,
frame->width = width;
frame->height = height;
+ frame->oheight = oheight;
frame->format = format;
- this->video_width = width;
- this->video_iheight = height;
- this->video_height = oheight;
- this->video_aspect = ratio_code;
-
- /* init encoder if needed */
-#if USE_LIBFAME
- if (!fc)
- {
- if (!(fc = fame_open ()))
- puts ("Couldn't start the FAME library");
-
- buffer = (unsigned char *) malloc (DEFAULT_BUFFER_SIZE);
- fp.quality=this->config->register_range(this->config,"dxr3enc.quality",90, 10,100, "Dxr3enc: mpeg encoding quality",NULL,NULL,NULL);
- /* the really interesting bit is the quantizer scale. The formula
- * below is copied from libfame's sources (could be changed in the
- * future) */
- printf("dxr3enc: quality %d -> quant scale = %d\n", fp.quality,
- 1 + (30*(100-fp.quality)+50)/100);
- fp.width = width;
- fp.height = oheight;
- fp.profile = "mpeg1";
- fp.coding = "I";
- fp.verbose = 0; /* we don't need any more info.. thanks :) */
-
- /* start guessing the framerate */
- fps = 90000.0/frame->vo_frame.duration;
- if (fabs(fps - 25) < 0.01) { /* PAL */
- printf("dxr3enc: setting mpeg output framerate to PAL (25 Hz)\n");
- fp.frame_rate_num = 25; fp.frame_rate_den = 1;
- }
- else if (fabs(fps - 24) < 0.01) { /* FILM */
- printf("dxr3enc: setting mpeg output framerate to FILM (24 Hz))\n");
- fp.frame_rate_num = 24; fp.frame_rate_den = 1;
- }
- else if (fabs(fps - 23.976) < 0.01) { /* NTSC-FILM */
- printf("dxr3enc: setting mpeg output framerate to NTSC-FILM (23.976 Hz))\n");
- fp.frame_rate_num = 24000; fp.frame_rate_den = 1001;
- }
- else if (fabs(fps - 29.97) < 0.01) { /* NTSC */
- printf("dxr3enc: setting mpeg output framerate to NTSC (29.97 Hz)\n");
- fp.frame_rate_num = 30000; fp.frame_rate_den = 1001;
- }
- else { /* try 1/fps, if not legal, libfame will go to PAL */
- fp.frame_rate_num = (int)(fps + 0.5); fp.frame_rate_den = 1;
- printf("dxr3enc: trying to set mpeg output framerate to %d Hz\n",
- fp.frame_rate_num);
- }
- fame_init (fc, &fp, buffer, DEFAULT_BUFFER_SIZE);
- }
-#endif
-#if USE_FFMPEG
- if (!avc)
- {
- avc = malloc(sizeof(AVCodecContext));
- memset(avc, 0, sizeof(AVCodecContext));
- buffer = (unsigned char *) malloc (DEFAULT_BUFFER_SIZE);
-
- avc->bit_rate = 0; /* using fixed quantizer */
- avc->width = width;
- avc->height = oheight;
- avc->gop_size = 0; /* only intra */
- avc->pix_fmt = PIX_FMT_YUV420P;
- avc->flags = CODEC_FLAG_QSCALE; /* fix qscale = quality */
- avc->quality = 2; /* 1-31 highest-lowest quality */
- /* start guessing the framerate */
- fps = 90000.0/frame->vo_frame.duration;
- avc->frame_rate = (int)(fps*FRAME_RATE_BASE + 0.5);
-
- if (avcodec_open(avc, avcodec)) {
- printf("dxr3enc: error opening avcodec. Aborting...\n");
- exit(1); /* can't think of a cleaner way at this point */
- }
- }
-#endif
-#if USE_MP1E
- if (context == 0) {
- enum rte_mux_mode mux_mode = RTE_VIDEO;
- /* rte_codec *codec; */
- enum rte_frame_rate frame_rate;
- enum rte_pixformat pixformat;
- char tmpstr[128];
-
- if (format != IMGFMT_YV12) {
- /* not supported yet; I need to fix the black bar stuff for YUYV
- buffers first... can't use the internal yuyv->yuv420 translation
- if sending data from display_frame... */
- printf("dxr3enc: format not supported yet with mp1e encoder.\n");
- exit(1);
- }
-
- if (! rte_init() ) {
- printf("dxr3enc: failed to init librte; exiting...\n");
- exit(1);
- }
- context = rte_context_new (width, oheight, "mp1e", NULL);
- rte_set_verbosity(context, 2);
- /* rte_codec_set seems to create a program stream ... */
- /*codec = rte_codec_set(context, RTE_STREAM_VIDEO, 0, "mpeg1-video");*/
- rte_set_mode(context, mux_mode);
-
- /* start guessing the framerate */
- fps = 90000.0/frame->vo_frame.duration;
- if (fabs(fps - 23.976) < 0.01) { /* NTSC-FILM */
- printf("dxr3enc: setting mpeg output framerate to NTSC-FILM (23.976 Hz))\n");
- frame_rate = RTE_RATE_1;
- }
- else if (fabs(fps - 24) < 0.01) { /* FILM */
- printf("dxr3enc: setting mpeg output framerate to FILM (24 Hz))\n");
- frame_rate = RTE_RATE_2;
- }
- else if (fabs(fps - 25) < 0.01) { /* PAL */
- printf("dxr3enc: setting mpeg output framerate to PAL (25 Hz)\n");
- frame_rate = RTE_RATE_3;
- }
- else if (fabs(fps - 29.97) < 0.01) { /* NTSC */
- printf("dxr3enc: setting mpeg output framerate to NTSC (29.97 Hz)\n");
- frame_rate = RTE_RATE_4;
- }
- else { /* go to PAL */
- frame_rate = RTE_RATE_3;
- printf("dxr3enc: can't do %g Hz, using PAL\n", fps);
- }
- pixformat = (format == IMGFMT_YV12 ? RTE_YUV420 : RTE_YUYV);
- rte_bitrate=this->config->register_range(this->config,"dxr3enc.bitrate",5000, 500,10000, "Dxr3enc: rte mpeg output bitrate (kbit/s)",NULL,NULL,NULL);
- rte_bitrate *= 1000;
- if (!rte_set_video_parameters(context, pixformat,
- context->width, context->height, frame_rate, rte_bitrate, "I")) {
- printf("dxr3enc: set_video_parameters failed: %s\n",
- context->error);
- rte_context_destroy(context);
- exit(1);
- }
- /* paranoid; make sure we don't do motion searching */
- rte_set_motion(context, 0, 0);
- rte_set_input(context, RTE_VIDEO, RTE_PUSH, FALSE, NULL, NULL, NULL);
- snprintf (tmpstr, sizeof(tmpstr), "%s_mv", devname);
- rte_set_output(context, NULL, NULL, tmpstr);
- if (!rte_init_context(context)) {
- printf("dxr3enc: cannot init the context: %s\n",
- context->error);
- rte_context_delete(context);
- exit(1);
- }
- /* do the sync'ing and start encoding */
- if (!rte_start_encoding(context)) {
- printf("dxr3enc: cannot start encoding: %s\n",
- context->error);
- rte_context_delete(context);
- exit(1);
- }
- rte_ptr = rte_push_video_data(context, NULL, 0);
- if (! rte_ptr) {
- printf("dxr3enc: failed to get encoder buffer pointer.\n");
- exit(1);
- }
- rte_time = 0.0;
- rte_time_step = frame->vo_frame.duration/90000.;
- }
-#endif
if(this->aspectratio!=aspect)
dxr3_set_property (this_gen,VO_PROP_ASPECT_RATIO, aspect);
-#if USE_MPEG_BUFFER
- /* safeguard */
- frame->mpeg_size = 0;
-#endif
}
static void dxr3_frame_copy(vo_frame_t *frame_gen, uint8_t **src)
{
- int size, i, j, hoffset, w2;
- dxr3_frame_t *frame = (dxr3_frame_t *) frame_gen;
- dxr3_driver_t *this = frame->vo_instance;
- uint8_t *y, *u, *v, *yuy2;
-
- if (frame_gen->bad_frame)
- return;
-
- if (frame->copy_calls == frame->height/16) {
- /* shouldn't happen */
- printf("dxr3enc: Internal error. Too many calls to dxr3_frame_copy (%d)\n",
- frame->copy_calls);
- return;
- }
-
- if (frame_gen->format == IMGFMT_YV12) {
- y = frame->real_base[0];
- u = frame->real_base[1];
- v = frame->real_base[2];
- }
- else { /* must be YUY2 */
- if (! (this->out[0] && this->out[1] && this->out[2]) ) {
- printf("dxr3enc: Internal error. Internal YV12 buffer not created.\n");
- return;
- }
- /* need conversion */
- hoffset = (this->oheight - frame->height)/2;
- y = this->out[0] + frame->width*(hoffset + frame->copy_calls*16);
- u = this->out[1] + frame->width/2*(hoffset/2 + frame->copy_calls*8);
- v = this->out[2] + frame->width/2*(hoffset/2 + frame->copy_calls*8);
- yuy2 = src[0];
- w2 = frame->width/2;
- /* we get 16 lines each time */
- for (i=0; i<16; i+=2) {
- for (j=0; j<w2; j++) {
- /* packed YUV 422 is: Y[i] U[i] Y[i+1] V[i] */
- *(y++) = *(yuy2++);
- *(u++) = *(yuy2++);
- *(y++) = *(yuy2++);
- *(v++) = *(yuy2++);
- }
- /* down sampling */
- for (j=0; j<w2; j++) {
- /* skip every second line for U and V */
- *(y++) = *(yuy2++);
- yuy2++;
- *(y++) = *(yuy2++);
- yuy2++;
- }
- }
- /* reset for encoder */
- y = this->out[0];
- u = this->out[1];
- v = this->out[2];
- }
-
- frame->copy_calls++;
-
- /* frame complete yet? */
- if (frame->copy_calls == frame->height/16) {
-#if USE_LIBFAME
- yuv.y=y;
- yuv.u=u;
- yuv.v=v;
- size = fame_encode_frame(fc, &yuv, NULL);
- /* not sure whether libfame does bounds checking, but if we're
- * this close to the limit there's bound to be trouble */
- if (size >= DEFAULT_BUFFER_SIZE) {
- printf("dxr3enc: warning, mpeg buffer too small!\n");
- size = DEFAULT_BUFFER_SIZE;
- }
-# if USE_MPEG_BUFFER
- /* copy mpeg data to frame */
- xine_fast_memcpy(frame->mpeg, buffer, size);
- frame->mpeg_size = size;
-# endif
-#endif
-#if USE_FFMPEG
- avp.data[0] = y;
- avp.data[1] = u;
- avp.data[2] = v;
- avp.linesize[0] = frame->width;
- avp.linesize[1] = avp.linesize[2] = frame->width/2;
-# if USE_MPEG_BUFFER
- size = avcodec_encode_video(avc, frame->mpeg, DEFAULT_BUFFER_SIZE, &avp);
- frame->mpeg_size = size;
-# else
- size = avcodec_encode_video(avc, buffer, DEFAULT_BUFFER_SIZE, &avp);
-# endif
-#endif
-#if USE_MP1E
- rte_time += rte_time_step;
-#endif
-#if (!USE_MPEG_BUFFER) && (!USE_MP1E)
- /* write to device now */
- if (write(this->fd_video, buffer, size) < 0)
- perror("dxr3enc: writing to video device");
-#endif
- }
+ dxr3_frame_t *frame = (dxr3_frame_t *) frame_gen;
+ dxr3_driver_t *this = frame->vo_instance;
+ if (this->enc && this->enc->on_frame_copy)
+ this->enc->on_frame_copy(this, frame, src);
}
-#define MV_COMMAND 0
-
static void dxr3_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen)
{
- char tmpstr[256];
- int size;
dxr3_driver_t *this = (dxr3_driver_t*)this_gen;
dxr3_frame_t *frame = (dxr3_frame_t*)frame_gen;
-#if USE_MAGIC_REGISTER
- em8300_register_t regs;
- regs.microcode_register=1; /* Yes, this is a MC Reg */
- regs.reg = MV_COMMAND;
- regs.val=6; /* Mike's mystery number :-) */
- ioctl(this->fd_control, EM8300_IOCTL_WRITEREG, &regs);
-#endif
-#if USE_MP1E
- size = frame->width * this->oheight;
- /* we should make real_base contiguous */
- xine_fast_memcpy(rte_ptr, frame->real_base[0], size);
- xine_fast_memcpy(rte_ptr+size, frame->real_base[1], size/4);
- xine_fast_memcpy(rte_ptr+size*5/4, frame->real_base[2], size/4);
- rte_ptr = rte_push_video_data(context, rte_ptr, rte_time);
-#endif
-#if USE_MPEG_BUFFER
- if (this->fd_video < 0) {
- snprintf (tmpstr, sizeof(tmpstr), "%s_mv", devname);
- this->fd_video = open(tmpstr, O_WRONLY);
- }
- if (write(this->fd_video, frame->mpeg, frame->mpeg_size) < 0)
- perror("dxr3enc: writing to video device");
-#endif
- frame_gen->displayed (frame_gen);
+ if (this->enc)
+ this->enc->on_display_frame(this, frame);
+
+ /* plugin is responsible for calling vo_frame->displayed(frame) ! */
}
static void dxr3_overlay_blend (vo_driver_t *this_gen, vo_frame_t *frame_gen,
vo_overlay_t *overlay)
{
- /* dxr3_driver_t *this = (dxr3_driver_t *) this_gen; */
- /*fprintf(stderr, "dxr3_vo: dummy function dxr3_overlay_blend called!\n");*/
+ /* dummy function */
}
void dxr3_exit (vo_driver_t *this_gen)
{
dxr3_driver_t *this = (dxr3_driver_t *) this_gen;
+ if (this->enc && this->enc->on_close)
+ this->enc->on_close(this);
if(this->overlay_enabled)
- dxr3_overlay_set_mode(&this->overlay, EM8300_OVERLAY_MODE_OFF );
- close(this->fd_control);
-#if USE_MP1E
- if (context) {
- rte_stop(context);
- rte_context_delete(context);
- context = 0;
- }
-#endif
+ dxr3_overlay_set_mode(&this->overlay, EM8300_OVERLAY_MODE_OFF);
}
vo_driver_t *init_video_out_plugin (config_values_t *config, void *visual_gen)
{
dxr3_driver_t *this;
char tmpstr[100];
- char *file_out;
+ const char *encoder;
+ char *available_encoders,*default_encoder;
/*
* allocate plugin struct
@@ -673,20 +414,21 @@ vo_driver_t *init_video_out_plugin (config_values_t *config, void *visual_gen)
this->vo_driver.exit = dxr3_exit;
this->config=config;
+ this->enhanced_mode = config->register_bool(config,"dxr3enc.alt_play_mode", 1, "Dxr3enc: use alternate Play mode","Enabling this option will utilise a slightly different play mode",NULL,NULL);
/* open control device */
- devname = config->register_string (config, LOOKUP_DEV, DEFAULT_DEV,NULL,NULL,NULL,NULL);
+ this->devname = config->register_string (config, LOOKUP_DEV, DEFAULT_DEV,NULL,NULL,NULL,NULL);
- printf("dxr3enc: Entering video init, devname=%s.\n",devname);
- if ((this->fd_control = open(devname, O_WRONLY)) < 0) {
+ printf("dxr3enc: Entering video init, devname=%s.\n",this->devname);
+ if ((this->fd_control = open(this->devname, O_WRONLY)) < 0) {
printf("dxr3enc: Failed to open control device %s (%s)\n",
- devname, strerror(errno));
+ this->devname, strerror(errno));
return 0;
}
/* output mpeg to file instead of dxr3? */
- file_out = config->register_string(config, "dxr3enc.outputfile", "<none>", "Dxr3enc: output file for debugging",NULL,NULL,NULL);
+ this->file_out = config->register_string(config, "dxr3enc.outputfile", "<none>", "Dxr3enc: output file for debugging",NULL,NULL,NULL);
- if (file_out && strcmp(file_out, "<none>")) {
- this->fd_video = open(file_out, O_WRONLY | O_CREAT);
+ if (this->file_out && strcmp(this->file_out, "<none>")) {
+ this->fd_video = open(this->file_out, O_WRONLY | O_CREAT);
if (this->fd_video < 0) {
perror("dxr3enc: failed to open output file");
return 0;
@@ -694,19 +436,53 @@ vo_driver_t *init_video_out_plugin (config_values_t *config, void *visual_gen)
}
else {
/* open video device */
- snprintf (tmpstr, sizeof(tmpstr), "%s_mv", devname);
+ snprintf (tmpstr, sizeof(tmpstr), "%s_mv", this->devname);
if ((this->fd_video = open (tmpstr, O_WRONLY | O_SYNC )) < 0) {
printf("dxr3enc: failed to open video device %s (%s)\n",
tmpstr, strerror(errno));
return 0;
}
-#if USE_MPEG_BUFFER || USE_MP1E
- /* we have to close now and open the first time we get
- * to display_frame. weird... */
+ /* close now and and let the encoders reopen if they want */
close(this->fd_video);
this->fd_video = -1;
+ }
+
+ /* which encoder to use? Whadda we got? */
+ default_encoder = 0;
+ /* memory leak... but config doesn't copy our help string :-( */
+ available_encoders = malloc(256);
+ strcpy(available_encoders, "Mpeg1 encoder. Options: ");
+#ifdef HAVE_LIBFAME
+ default_encoder = "fame";
+ strcat(available_encoders, "\"fame\" (very fast, good quality) ");
+#endif
+#ifdef HAVE_LIBRTE
+ default_encoder = "rte";
+ strcat(available_encoders, "\"rte\" (fast, high quality) ");
+#endif
+ printf("dxr3enc: %s\n", available_encoders);
+ if (! default_encoder) { /* silly person; no encoder compiled in! */
+ printf("dxr3enc: no mpeg1 encoder compiled in.\n");
+ return 0;
+ }
+ encoder = config->register_string(config, "dxr3enc.encoder",
+ default_encoder, available_encoders, NULL, NULL, NULL);
+ this->enc = 0;
+#ifdef HAVE_LIBRTE
+ if (! strcmp(encoder, "rte"))
+ if ( dxr3enc_rte_init(this) )
+ return 0;
#endif
+#ifdef HAVE_LIBFAME
+ if (! strcmp(encoder, "fame"))
+ if ( dxr3enc_fame_init(this) )
+ return 0;
+#endif
+ if (! this->enc) {
+ printf("dxr3enc: encoder \"%s\" not supported.\n", encoder);
+ return 0;
}
+
gather_screen_vars(this, visual_gen);
/* default values */
@@ -720,26 +496,6 @@ vo_driver_t *init_video_out_plugin (config_values_t *config, void *visual_gen)
dxr3_overlay_buggy_preinit(&this->overlay, this->fd_control);
}
-#if USE_LIBFAME
- /* fame context */
- fc = 0;
-#endif
-#if USE_FFMPEG
- avc = 0;
- avcodec_init();
- /* this register_all() is not really needed, but it gives us a good
- * way to sniff out bad libavcodecs */
- avcodec_register_all();
- avcodec = avcodec_find_encoder(CODEC_ID_MPEG1VIDEO);
- if (! avcodec) {
- /* tell tale sign of bad libavcodec */
- printf("dxr3enc: can't find mpeg1 encoder! libavcodec is rotten!\n");
- return 0;
- }
-#endif
-#if USE_MP1E
- context = 0;
-#endif
return &this->vo_driver;
}
@@ -756,3 +512,393 @@ vo_info_t *get_video_out_plugin_info()
return &vo_info_dxr3;
}
+#ifdef HAVE_LIBRTE
+
+static void mp1e_callback(rte_context *context, void *data, ssize_t size,
+ void* user_data)
+{
+ dxr3_driver_t *this = (dxr3_driver_t*)user_data;
+ em8300_register_t regs;
+ char tmpstr[128];
+
+ if (this->enhanced_mode)
+ {
+ regs.microcode_register=1; /* Yes, this is a MC Reg */
+ regs.reg = MV_COMMAND;
+ regs.val=6; /* Mike's mystery number :-) */
+ ioctl(this->fd_control, EM8300_IOCTL_WRITEREG, &regs);
+ }
+ if (this->fd_video < 0) {
+ snprintf (tmpstr, sizeof(tmpstr), "%s_mv", this->devname);
+ this->fd_video = open(tmpstr, O_WRONLY);
+ }
+ if (write(this->fd_video, data, size) < 0)
+ perror("dxr3enc: writing to video device");
+}
+
+static int rte_on_update_format(dxr3_driver_t *drv)
+{
+ rte_data_t *this = (rte_data_t*)drv->enc;
+ rte_context* context;
+ enum rte_mux_mode mux_mode = RTE_VIDEO;
+ /* rte_codec *codec; */
+ enum rte_frame_rate frame_rate;
+ enum rte_pixformat pixformat;
+ int width, height;
+ double fps;
+ char tmpstr[128];
+
+ width = drv->video_width;
+ height = drv->video_height;
+
+ if (this->context != 0) /* already done */
+ return 0;
+
+ this->context = rte_context_new (width, height, "mp1e", drv);
+ if (! this->context) {
+ printf("failed to get rte context.\n");
+ return 1;
+ }
+ context = this->context; /* shortcut */
+ rte_set_verbosity(context, 2);
+ /* rte_codec_set seems to create a program stream ... */
+ /*codec = rte_codec_set(context, RTE_STREAM_VIDEO, 0, "mpeg1-video");*/
+ rte_set_mode(context, mux_mode);
+
+ /* start guessing the framerate */
+ fps = drv->fps;
+ if (fabs(fps - 23.976) < 0.01) { /* NTSC-FILM */
+ printf("dxr3enc: setting mpeg output framerate to NTSC-FILM (23.976 Hz))\n");
+ frame_rate = RTE_RATE_1;
+ }
+ else if (fabs(fps - 24) < 0.01) { /* FILM */
+ printf("dxr3enc: setting mpeg output framerate to FILM (24 Hz))\n");
+ frame_rate = RTE_RATE_2;
+ }
+ else if (fabs(fps - 25) < 0.01) { /* PAL */
+ printf("dxr3enc: setting mpeg output framerate to PAL (25 Hz)\n");
+ frame_rate = RTE_RATE_3;
+ }
+ else if (fabs(fps - 29.97) < 0.01) { /* NTSC */
+ printf("dxr3enc: setting mpeg output framerate to NTSC (29.97 Hz)\n");
+ frame_rate = RTE_RATE_4;
+ }
+ else { /* go to PAL */
+ frame_rate = RTE_RATE_3;
+ printf("dxr3enc: can't do %g Hz, using PAL\n", fps);
+ }
+ pixformat = (drv->format == IMGFMT_YV12 ? RTE_YUV420 : RTE_YUYV);
+ this->rte_bitrate=drv->config->register_range(drv->config,"dxr3enc.rte_bitrate",10000, 1000,20000, "Dxr3enc: rte mpeg output bitrate (kbit/s)",NULL,NULL,NULL);
+ this->rte_bitrate *= 1000;
+ if (!rte_set_video_parameters(context, pixformat,
+ context->width, context->height, frame_rate,
+ this->rte_bitrate, "I")) {
+ printf("dxr3enc: set_video_parameters failed: %s\n",
+ context->error);
+ rte_context_destroy(context);
+ context = 0;
+ return 1;
+ }
+
+ /* paranoid; make sure we don't do motion searching */
+ rte_set_motion(context, 0, 0);
+ rte_set_input(context, RTE_VIDEO, RTE_PUSH, FALSE, NULL, NULL, NULL);
+ snprintf (tmpstr, sizeof(tmpstr), "%s_mv", drv->devname);
+ //rte_set_output(context, NULL, NULL, tmpstr);
+ rte_set_output(context, mp1e_callback, NULL, NULL);
+ if (!rte_init_context(context)) {
+ printf("dxr3enc: cannot init the context: %s\n",
+ context->error);
+ rte_context_delete(context);
+ context = 0;
+ return 1;
+ }
+ /* do the sync'ing and start encoding */
+ if (!rte_start_encoding(context)) {
+ printf("dxr3enc: cannot start encoding: %s\n",
+ context->error);
+ rte_context_delete(context);
+ context = 0;
+ return 1;
+ }
+ this->rte_ptr = rte_push_video_data(context, NULL, 0);
+ if (! this->rte_ptr) {
+ printf("dxr3enc: failed to get encoder buffer pointer.\n");
+ return 1;
+ }
+ this->rte_time = 0.0;
+ this->rte_time_step = 1.0/fps;
+
+ return 0;
+}
+
+static int rte_on_display_frame( dxr3_driver_t* drv, dxr3_frame_t* frame )
+{
+ int size;
+ rte_data_t* this = (rte_data_t*)drv->enc;
+ size = frame->width * frame->oheight;
+ if (frame->format == IMGFMT_YV12)
+ xine_fast_memcpy(this->rte_ptr, frame->real_base[0], size*3/2);
+ else
+ xine_fast_memcpy(this->rte_ptr, frame->real_base[0], size*2);
+ this->rte_time += this->rte_time_step;
+ this->rte_ptr = rte_push_video_data(this->context, this->rte_ptr,
+ this->rte_time);
+ frame->vo_frame.displayed(&frame->vo_frame);
+ return 0;
+}
+
+static int rte_on_close( dxr3_driver_t *drv )
+{
+ rte_data_t *this = (rte_data_t*)drv->enc;
+ if (this->context) {
+ rte_stop(this->context);
+ rte_context_delete(this->context);
+ this->context = 0;
+ }
+ free(this);
+ drv->enc = 0;
+ return 0;
+}
+
+int dxr3enc_rte_init( dxr3_driver_t *drv )
+{
+ rte_data_t* this;
+ if (! rte_init() ) {
+ printf("dxr3enc: failed to init librte\n");
+ return 1;
+ }
+ this = malloc(sizeof(rte_data_t));
+ if (!this)
+ return 1;
+ memset(this, 0, sizeof(rte_data_t));
+ this->encoder_data.type = ENC_RTE;
+ this->context = 0;
+ this->encoder_data.on_update_format = rte_on_update_format;
+ this->encoder_data.on_frame_copy = 0;
+ this->encoder_data.on_display_frame = rte_on_display_frame;
+ this->encoder_data.on_close = rte_on_close;
+ drv->enc = (encoder_data_t*)this;
+ return 0;
+}
+
+#endif
+
+#ifdef HAVE_LIBFAME
+
+static fame_parameters_t dummy_init_fp = FAME_PARAMETERS_INITIALIZER;
+
+static int fame_on_update_format(dxr3_driver_t *drv)
+{
+ fame_data_t *this = (fame_data_t*)drv->enc;
+ double fps;
+
+ /* if YUY2 and dimensions changed, we need to re-allocate the
+ * internal YV12 buffer */
+ if (this->buf) free(this->buf);
+ this->buf = 0;
+ this->out[0] = this->out[1] = this->out[2] = 0;
+ if (drv->format == IMGFMT_YUY2) {
+ int image_size = drv->video_width * drv->video_height;
+
+ this->out[0] = malloc_aligned(16, image_size * 3/2,
+ (void*)&this->buf);
+ 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);
+
+ printf("dxr3enc: Using YUY2->YV12 conversion\n");
+ }
+
+ if (!this->fc)
+ this->fc = fame_open();
+ if (!this->fc) {
+ printf("Couldn't start the FAME library\n");
+ return 1;
+ }
+
+ if (!this->buffer)
+ this->buffer = (unsigned char *) malloc (DEFAULT_BUFFER_SIZE);
+ if (!this->buffer) {
+ printf("Couldn't allocate temp buffer for mpeg data\n");
+ return 1;
+ }
+
+ this->fp = dummy_init_fp;
+ this->fp.quality=drv->config->register_range(drv->config,"dxr3enc.fame_quality",90, 10,100, "Dxr3enc: fame mpeg encoding quality",NULL,NULL,NULL);
+ /* the really interesting bit is the quantizer scale. The formula
+ * below is copied from libfame's sources (could be changed in the
+ * future) */
+ printf("dxr3enc: quality %d -> quant scale = %d\n", this->fp.quality,
+ 1 + (30*(100-this->fp.quality)+50)/100);
+ this->fp.width = drv->video_width;
+ this->fp.height = drv->video_height;
+ this->fp.profile = "mpeg1";
+ this->fp.coding = "I";
+ this->fp.verbose = 1; /* we don't need any more info.. thanks :) */
+
+ /* start guessing the framerate */
+ fps = drv->fps;
+ if (fabs(fps - 25) < 0.01) { /* PAL */
+ printf("dxr3enc: setting mpeg output framerate to PAL (25 Hz)\n");
+ this->fp.frame_rate_num = 25; this->fp.frame_rate_den = 1;
+ }
+ else if (fabs(fps - 24) < 0.01) { /* FILM */
+ printf("dxr3enc: setting mpeg output framerate to FILM (24 Hz))\n");
+ this->fp.frame_rate_num = 24; this->fp.frame_rate_den = 1;
+ }
+ else if (fabs(fps - 23.976) < 0.01) { /* NTSC-FILM */
+ printf("dxr3enc: setting mpeg output framerate to NTSC-FILM (23.976 Hz))\n");
+ this->fp.frame_rate_num = 24000; this->fp.frame_rate_den = 1001;
+ }
+ else if (fabs(fps - 29.97) < 0.01) { /* NTSC */
+ printf("dxr3enc: setting mpeg output framerate to NTSC (29.97 Hz)\n");
+ this->fp.frame_rate_num = 30000; this->fp.frame_rate_den = 1001;
+ }
+ else { /* try 1/fps, if not legal, libfame will go to PAL */
+ this->fp.frame_rate_num = (int)(fps + 0.5); this->fp.frame_rate_den = 1;
+ printf("dxr3enc: trying to set mpeg output framerate to %d Hz\n",
+ this->fp.frame_rate_num);
+ }
+ fame_init (this->fc, &this->fp, this->buffer, DEFAULT_BUFFER_SIZE);
+
+ return 0;
+}
+
+static int fame_on_frame_copy(dxr3_driver_t *drv, dxr3_frame_t *frame,
+ uint8_t **src)
+{
+ int size, i, j, hoffset, w2;
+ uint8_t *y, *u, *v, *yuy2;
+ fame_data_t *this = (fame_data_t*)drv->enc;
+
+ if (frame->vo_frame.bad_frame)
+ return 0;
+
+ if (frame->copy_calls == frame->height/16) {
+ /* shouldn't happen */
+ printf("dxr3enc: Internal error. Too many calls to dxr3_frame_copy (%d)\n",
+ frame->copy_calls);
+ return 1;
+ }
+
+ if (frame->vo_frame.format == IMGFMT_YUY2) {
+ /* need YUY2->YV12 conversion */
+ if (! (this->out[0] && this->out[1] && this->out[2]) ) {
+ printf("dxr3enc: Internal error. Internal YV12 buffer not created.\n");
+ return 1;
+ }
+ /* need conversion */
+ hoffset = ((frame->oheight - frame->height)/32)*16;
+ y = this->out[0] + frame->width*(hoffset + frame->copy_calls*16);
+ u = this->out[1] + frame->width/2*(hoffset/2 + frame->copy_calls*8);
+ v = this->out[2] + frame->width/2*(hoffset/2 + frame->copy_calls*8);
+ yuy2 = src[0];
+ w2 = frame->width/2;
+ /* we get 16 lines each time */
+ for (i=0; i<16; i+=2) {
+ for (j=0; j<w2; j++) {
+ /* packed YUV 422 is: Y[i] U[i] Y[i+1] V[i] */
+ *(y++) = *(yuy2++);
+ *(u++) = *(yuy2++);
+ *(y++) = *(yuy2++);
+ *(v++) = *(yuy2++);
+ }
+ /* down sampling */
+ for (j=0; j<w2; j++) {
+ /* skip every second line for U and V */
+ *(y++) = *(yuy2++);
+ yuy2++;
+ *(y++) = *(yuy2++);
+ yuy2++;
+ }
+ }
+ /* reset for encoder */
+ y = this->out[0];
+ u = this->out[1];
+ v = this->out[2];
+ }
+ else { /* YV12 */
+ y = frame->real_base[0];
+ u = frame->real_base[1];
+ v = frame->real_base[2];
+ }
+
+ frame->copy_calls++;
+
+ /* frame complete yet? */
+ if (frame->copy_calls != frame->height/16)
+ return 0;
+ /* frame is complete: encode */
+ this->yuv.y=y;
+ this->yuv.u=u;
+ this->yuv.v=v;
+ size = fame_encode_frame(this->fc, &this->yuv, NULL);
+ if (size >= DEFAULT_BUFFER_SIZE) {
+ printf("dxr3enc: warning, mpeg buffer too small!\n");
+ size = DEFAULT_BUFFER_SIZE;
+ }
+ /* copy mpeg data to frame */
+ xine_fast_memcpy(frame->mpeg, this->buffer, size);
+ frame->mpeg_size = size;
+ return 0;
+}
+
+
+static int fame_on_display_frame( dxr3_driver_t* drv, dxr3_frame_t* frame)
+{
+ char tmpstr[128];
+ em8300_register_t regs;
+ if (drv->enhanced_mode)
+ {
+ regs.microcode_register=1; /* Yes, this is a MC Reg */
+ regs.reg = MV_COMMAND;
+ regs.val=6; /* Mike's mystery number :-) */
+ ioctl(drv->fd_control, EM8300_IOCTL_WRITEREG, &regs);
+ }
+
+ if (drv->fd_video < 0) {
+ snprintf (tmpstr, sizeof(tmpstr), "%s_mv", drv->devname);
+ drv->fd_video = open(tmpstr, O_WRONLY);
+ }
+ if (write(drv->fd_video, frame->mpeg, frame->mpeg_size) < 0)
+ perror("dxr3enc: writing to video device");
+ frame->vo_frame.displayed(&frame->vo_frame);
+ return 0;
+}
+
+static int fame_on_close( dxr3_driver_t *drv )
+{
+ fame_data_t *this = (fame_data_t*)drv->enc;
+ if (this->fc) {
+ fame_close(this->fc);
+ }
+ free(this);
+ drv->enc = 0;
+ return 0;
+}
+
+int dxr3enc_fame_init( dxr3_driver_t *drv )
+{
+ fame_data_t* this;
+ this = malloc(sizeof(fame_data_t));
+ if (! this)
+ return 1;
+ memset(this, 0, sizeof(fame_data_t));
+ this->encoder_data.type = ENC_FAME;
+ /* fame context */
+ this->fc = 0;
+ this->encoder_data.on_update_format = fame_on_update_format;
+ this->encoder_data.on_frame_copy = fame_on_frame_copy;
+ this->encoder_data.on_display_frame = fame_on_display_frame;
+ this->encoder_data.on_close = fame_on_close;
+ drv->enc = (encoder_data_t*)this;
+ return 0;
+}
+
+#endif
+
diff --git a/src/dxr3/dxr3_vo_encoder.h b/src/dxr3/dxr3_vo_encoder.h
deleted file mode 100644
index 6635f2c2f..000000000
--- a/src/dxr3/dxr3_vo_encoder.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright (C) 2000-2001 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- *
- * $Id: dxr3_vo_encoder.h,v 1.10 2001/12/02 21:14:51 hrm Exp $
- *
- */
-
-/*************************************************************************
- * Dxr3 Encoding Plugin Configuration Options *
- *************************************************************************/
-
-/* 1: enable to buffer the mpeg1 stream;
- * 0: write to mpeg device immediately;
- * with 1 sync is better, but playback still not smooth (but see below)
- * (not supported with mp1e; will disable automatically) */
-#define USE_MPEG_BUFFER 1
-
-/* 1: write 6 to MV_COMMAND register. This seems to fix playback problems!
- * 0: don't write to register */
-#define USE_MAGIC_REGISTER 1
-
-/* select one mpeg encoder out of the three below */
-#define USE_LIBFAME 1
-
-#define USE_FFMPEG 0
-
-#define USE_MP1E 0
-
-/*************************************************************************
- * Dxr3 Encoding private stuff below - You shouldn't need to change this *
- *************************************************************************/
-
-/* 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
-
-#if (USE_LIBFAME && USE_FFMPEG) || (USE_LIBFAME && USE_MP1E) || (USE_LIBFFMPEG && USE_MP1E)
-# error "Configure only one mpeg encoder"
-#endif
-
-#if USE_LIBFAME
- #include <fame.h>
-
- /* some global stuff for libfame, could use some cleanup :-) */
- fame_parameters_t fp = FAME_PARAMETERS_INITIALIZER;
- fame_yuv_t yuv;
- fame_context_t *fc; /* needed for fame calls */
-#endif
-
-#if USE_FFMPEG
- /* use libffmpeg */
- #include <ffmpeg/avcodec.h>
- AVCodecContext *avc;
- AVPicture avp;
- AVCodec *avcodec;
-#endif
-
-#if USE_MP1E
- #define _GNU_SOURCE
- #include <unistd.h>
- #include <rte.h>
- rte_context* context; /* handle for encoding */
- void* rte_ptr; /* buffer maintened by librte */
- double rte_time; /* frame time (s) */
- double rte_time_step; /* time per frame (s) */
- double rte_bitrate; /* mpeg out bitrate, default 2.3e6 bits/s */
-# undef USE_MPEG_BUFFER
-# define USE_MPEG_BUFFER 0
-#endif
-
-/* mpeg1 buffer, used by both encoders */
-unsigned char *buffer;
-
diff --git a/src/dxr3/dxr3_vo_standard.c b/src/dxr3/dxr3_vo_standard.c
index 9263cd71a..a466f04d2 100644
--- a/src/dxr3/dxr3_vo_standard.c
+++ b/src/dxr3/dxr3_vo_standard.c
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
- * $Id: dxr3_vo_standard.c,v 1.7 2001/11/25 20:21:25 hrm Exp $
+ * $Id: dxr3_vo_standard.c,v 1.8 2001/12/11 02:26:59 hrm Exp $
*
*******************************************************************
* Dummy video out plugin for the dxr3. Is responsible for setting *
@@ -65,12 +65,8 @@ static void dummy_frame_dispose (vo_frame_t *frame_gen)
{
dxr3_frame_t *frame = (dxr3_frame_t *) frame_gen;
- if (frame->mem[0])
- free (frame->mem[0]);
- if (frame->mem[1])
- free (frame->mem[1]);
- if (frame->mem[2])
- free (frame->mem[2]);
+ if (frame->mem)
+ free (frame->mem);
free(frame);
}
@@ -100,19 +96,10 @@ static void dxr3_update_frame_format (vo_driver_t *this_gen,
if ((frame->width != width) || (frame->height != height)
|| (frame->format != format)) {
- if (frame->mem[0]) {
- free (frame->mem[0]);
- frame->mem[0] = NULL;
+ if (frame->mem) {
+ free (frame->mem);
+ frame->mem = NULL;
}
- if (frame->mem[1]) {
- free (frame->mem[1]);
- frame->mem[1] = NULL;
- }
- if (frame->mem[2]) {
- free (frame->mem[2]);
- frame->mem[2] = NULL;
- }
-
frame->width = width;
frame->height = height;
frame->format = format;
@@ -133,15 +120,13 @@ static void dxr3_update_frame_format (vo_driver_t *this_gen,
if (format == IMGFMT_YV12) {
image_size = width * height;
- frame->vo_frame.base[0] = malloc_aligned(16,image_size,
- (void**) &frame->mem[0]);
- frame->vo_frame.base[1] = malloc_aligned(16,image_size/4,
- (void**) &frame->mem[1]);
- frame->vo_frame.base[2] = malloc_aligned(16,image_size/4,
- (void**) &frame->mem[2]);
+ frame->vo_frame.base[0] = malloc_aligned(16,image_size*3/2,
+ (void**) &frame->mem);
+ frame->vo_frame.base[1] = frame->vo_frame.base[0] + image_size;
+ frame->vo_frame.base[2] = frame->vo_frame.base[1] + image_size/4;
}else if (format == IMGFMT_YUY2) {
frame->vo_frame.base[0] = malloc_aligned(16, image_size*2,
- (void**)&frame->mem[0]);
+ (void**)&frame->mem);
frame->vo_frame.base[1] = frame->vo_frame.base[2] = 0;
}
}
@@ -202,11 +187,11 @@ vo_driver_t *init_video_out_plugin (config_values_t *config, void *visual_gen)
this->config = config;
/* open control device */
- devname = config->register_string (config, LOOKUP_DEV, DEFAULT_DEV, NULL,NULL,NULL,NULL);
+ this->devname = config->register_string (config, LOOKUP_DEV, DEFAULT_DEV, NULL,NULL,NULL,NULL);
- if ((this->fd_control = open(devname, O_WRONLY)) < 0) {
+ if ((this->fd_control = open(this->devname, O_WRONLY)) < 0) {
fprintf(stderr, "dxr3_vo: Failed to open control device %s (%s)\n",
- devname, strerror(errno));
+ this->devname, strerror(errno));
return 0;
}