summaryrefslogtreecommitdiff
path: root/src/dxr3/dxr3_decode_video.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/dxr3/dxr3_decode_video.c')
-rw-r--r--src/dxr3/dxr3_decode_video.c351
1 files changed, 201 insertions, 150 deletions
diff --git a/src/dxr3/dxr3_decode_video.c b/src/dxr3/dxr3_decode_video.c
index b6a037f75..f1c69dc3d 100644
--- a/src/dxr3/dxr3_decode_video.c
+++ b/src/dxr3/dxr3_decode_video.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_decode_video.c,v 1.16 2002/09/18 15:43:34 mroi Exp $
+ * $Id: dxr3_decode_video.c,v 1.17 2002/10/26 14:35:04 mroi Exp $
*/
/* dxr3 video decoder plugin.
@@ -38,6 +38,7 @@
#include "xine_internal.h"
#include "buffer.h"
#include "dxr3_scr.h"
+#include "video_out_dxr3.h"
#include "dxr3.h"
#define LOG_VID 1
@@ -57,7 +58,7 @@
#define HEADER_OFFSET 0
-/* plugin initialization function */
+/* plugin class initialization function */
static void *dxr3_init_plugin(xine_t *xine, void *);
@@ -76,55 +77,65 @@ plugin_info_t xine_plugin_info[] = {
};
-/* functions required by xine api */
-static char *dxr3_get_id(void);
-static void dxr3_init(video_decoder_t *this_gen, vo_instance_t *video_out);
-static void dxr3_decode_data(video_decoder_t *this_gen, buf_element_t *buf);
-static void dxr3_flush(video_decoder_t *this_gen);
-static void dxr3_reset(video_decoder_t *this_gen);
-static void dxr3_close(video_decoder_t *this_gen);
-static void dxr3_dispose(video_decoder_t *this_gen);
+/* 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 structure */
-typedef struct dxr3_decoder_s {
- video_decoder_t video_decoder;
- vo_instance_t *video_out;
- dxr3_scr_t *scr;
- xine_t *xine;
-
- char devname[128];
- char devnum[3];
- int fd_control;
- int fd_video; /* to access the dxr3 devices */
-
- int have_header_info;
- int width;
- int height;
- int aspect;
- int frame_rate_code;
- int repeat_first_field; /* mpeg stream header data */
-
- int force_aspect; /* when input plugin has better info, we are forced
- * to use a certain aspect */
- int last_width;
- int last_height;
- int last_aspect; /* used to detect changes for event sending */
-
- int sync_every_frame;
- int sync_retry;
- int enhanced_mode;
- int resync_window;
- int skip_count; /* syncing parameters */
-
- int correct_durations;
- int64_t last_vpts;
- int force_duration_window;
- int avg_duration; /* logic to correct broken frame rates */
+/* plugin instance functions */
+static void dxr3_decode_data(video_decoder_t *this_gen, buf_element_t *buf);
+static void dxr3_reset(video_decoder_t *this_gen);
+static void dxr3_flush(video_decoder_t *this_gen);
+static void dxr3_dispose(video_decoder_t *this_gen);
+
+/* plugin structures */
+typedef struct dxr3_decoder_class_s {
+ video_decoder_class_t video_decoder_class;
+
+ int instance; /* we allow only one instance of this plugin */
+ char devname[128];
+ char devnum[3];
+} dxr3_decoder_class_t;
+
+typedef struct dxr3_decoder_s {
+ video_decoder_t video_decoder;
+ dxr3_decoder_class_t *class;
+ xine_stream_t *stream;
+ dxr3_scr_t *scr;
+ dxr3_driver_t *dxr3_vo; /* we need to talk to the dxr3 video out */
+
+ int fd_control;
+ int fd_video; /* to access the dxr3 devices */
+
+ int have_header_info;
+ int width;
+ int height;
+ int aspect;
+ int frame_rate_code;
+ int repeat_first_field; /* mpeg stream header data */
+
+ int force_aspect; /* when input plugin has better info, we are forced
+ * to use a certain aspect */
+ int last_width;
+ int last_height;
+ int last_aspect; /* used to detect changes for event sending */
+
+ int sync_every_frame;
+ int sync_retry;
+ int enhanced_mode;
+ int resync_window;
+ int skip_count; /* syncing parameters */
+
+ int correct_durations;
+ int64_t last_vpts;
+ int force_duration_window;
+ int avg_duration; /* logic to correct broken frame rates */
} dxr3_decoder_t;
/* helper functions */
-static int dxr3_present(xine_t *xine);
+static int dxr3_present(xine_stream_t *stream);
static 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);
@@ -137,15 +148,12 @@ static void dxr3_update_correct_durations(void *this_gen, xine_cfg_entry_t
static void *dxr3_init_plugin(xine_t *xine, void *data)
{
- dxr3_decoder_t *this;
+ dxr3_decoder_class_t *this;
config_values_t *cfg;
const char *confstr;
int dashpos;
- int64_t cur_offset;
-
- if (!dxr3_present(xine)) return NULL;
- this = (dxr3_decoder_t *)malloc(sizeof (dxr3_decoder_t));
+ this = (dxr3_decoder_class_t *)malloc(sizeof (dxr3_decoder_class_t));
if (!this) return NULL;
cfg = xine->config;
@@ -163,49 +171,44 @@ static void *dxr3_init_plugin(xine_t *xine, void *data)
this->devnum[0] = '\0';
}
- this->video_decoder.get_identifier = dxr3_get_id;
- this->video_decoder.init = dxr3_init;
- this->video_decoder.decode_data = dxr3_decode_data;
- this->video_decoder.flush = dxr3_flush;
- this->video_decoder.reset = dxr3_reset;
- this->video_decoder.close = dxr3_close;
- this->video_decoder.dispose = dxr3_dispose;
+ 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->scr = NULL;
- this->xine = xine;
+ this->instance = 0;
- this->sync_every_frame = cfg->register_bool(cfg,
- "dxr3.sync_every_frame", 0, _("Try to sync video every frame"),
- _("This is relevant for progressive video only (most PAL films)."), 20,
- dxr3_update_sync_mode, this);
- this->enhanced_mode = cfg->register_bool(cfg,
- "dxr3.alt_play_mode", 1, _("Use alternate Play mode"),
- _("Enabling this option will utilise a smoother play mode."), 10,
- dxr3_update_enhanced_mode, this);
- this->correct_durations = cfg->register_bool(cfg,
- "dxr3.correct_durations", 0, _("Correct frame durations in broken streams"),
- _("Enable this for streams with wrong frame durations."), 10,
- dxr3_update_correct_durations, this);
-
- /* set a/v offset to compensate dxr3 internal delay */
- cur_offset = this->xine->metronom->get_option(this->xine->metronom, METRONOM_AV_OFFSET);
- this->xine->metronom->set_option(this->xine->metronom, METRONOM_AV_OFFSET, cur_offset - 21600);
-
- return &this->video_decoder;
+ return &this->video_decoder_class;
}
-static char *dxr3_get_id(void)
+static video_decoder_t *dxr3_open_plugin(video_decoder_class_t *class_gen, xine_stream_t *stream)
{
- return "dxr3-mpeg2";
-}
-
-static void dxr3_init(video_decoder_t *this_gen, vo_instance_t *video_out)
-{
- dxr3_decoder_t *this = (dxr3_decoder_t *)this_gen;
+ dxr3_decoder_t *this;
+ dxr3_decoder_class_t *class = (dxr3_decoder_class_t *)class_gen;
+ config_values_t *cfg;
char tmpstr[128];
+ int64_t cur_offset;
+
+ if (class->instance) return NULL;
+ if (!dxr3_present(stream)) return NULL;
- snprintf(tmpstr, sizeof(tmpstr), "%s%s", this->devname, this->devnum);
+ this = (dxr3_decoder_t *)malloc(sizeof (dxr3_decoder_t));
+ if (!this) return NULL;
+
+ cfg = stream->xine->config;
+
+ this->video_decoder.decode_data = dxr3_decode_data;
+ this->video_decoder.reset = dxr3_reset;
+ this->video_decoder.flush = dxr3_flush;
+ this->video_decoder.dispose = dxr3_dispose;
+
+ this->class = class;
+ this->stream = stream;
+ this->scr = NULL;
+ this->dxr3_vo = (dxr3_driver_t *)stream->video_driver;
+
+ snprintf(tmpstr, sizeof(tmpstr), "%s%s", class->devname, class->devnum);
#if LOG_VID
printf("dxr3_decode_video: Entering video init, devname=%s.\n",tmpstr);
#endif
@@ -216,12 +219,10 @@ static void dxr3_init(video_decoder_t *this_gen, vo_instance_t *video_out)
if ((this->fd_control = open(tmpstr, O_WRONLY)) < 0) {
printf("dxr3_decode_video: Failed to open control device %s (%s)\n",
tmpstr, strerror(errno));
- return;
+ free(this);
+ return NULL;
}
- video_out->open(video_out);
- this->video_out = video_out;
-
this->have_header_info = 0;
this->repeat_first_field = 0;
@@ -236,11 +237,51 @@ static void dxr3_init(video_decoder_t *this_gen, vo_instance_t *video_out)
this->skip_count = 0;
this->force_duration_window = -FORCE_DURATION_WINDOW_SIZE;
- this->last_vpts =
- this->xine->metronom->get_current_time(this->xine->metronom);
+ this->last_vpts = this->stream->metronom->get_current_time(this->stream->metronom);
this->avg_duration = 0;
+
+ this->sync_every_frame = cfg->register_bool(cfg,
+ "dxr3.sync_every_frame", 0, _("Try to sync video every frame"),
+ _("This is relevant for progressive video only (most PAL films)."), 20,
+ dxr3_update_sync_mode, this);
+ this->enhanced_mode = cfg->register_bool(cfg,
+ "dxr3.alt_play_mode", 1, _("Use alternate Play mode"),
+ _("Enabling this option will utilise a smoother play mode."), 10,
+ dxr3_update_enhanced_mode, this);
+ this->correct_durations = cfg->register_bool(cfg,
+ "dxr3.correct_durations", 0, _("Correct frame durations in broken streams"),
+ _("Enable this for streams with wrong frame durations."), 10,
+ dxr3_update_correct_durations, this);
+
+ if (!this->dxr3_vo->overlay_enabled) {
+ /* set a/v offset to compensate dxr3 internal delay */
+ cur_offset = this->stream->metronom->get_option(this->stream->metronom, METRONOM_AV_OFFSET);
+ this->stream->metronom->set_option(this->stream->metronom, METRONOM_AV_OFFSET, cur_offset - 21600);
+ }
+
+ stream->video_out->open(stream->video_out);
+
+ class->instance = 1;
+
+ 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;
@@ -262,12 +303,16 @@ static void dxr3_decode_data(video_decoder_t *this_gen, buf_element_t *buf)
this->aspect = this->force_aspect = XINE_VO_ASPECT_PAN_SCAN;
/* when aspect changed, we have to send an event for dxr3 spu decoder */
if (!this->last_aspect || this->last_aspect != this->aspect) {
- xine_frame_change_event_t event;
- event.event.type = XINE_EVENT_FRAME_CHANGE;
- event.width = this->last_width;
- event.height = this->last_height;
- event.aspect = this->aspect;
- xine_send_event(this->xine, &event.event);
+ xine_event_t event;
+ xine_format_change_data_t data;
+ event.type = XINE_EVENT_FRAME_FORMAT_CHANGE;
+ event.stream = this->stream;
+ event.data = &data;
+ event.data_length = sizeof(data);
+ data.width = this->last_width;
+ data.height = this->last_height;
+ data.aspect = this->aspect;
+ xine_event_send(this->stream, &event);
this->last_aspect = this->aspect;
}
}
@@ -318,7 +363,7 @@ static void dxr3_decode_data(video_decoder_t *this_gen, buf_element_t *buf)
continue;
/* pretend like we have decoded a frame */
- img = this->video_out->get_frame (this->video_out,
+ img = this->stream->video_out->get_frame(this->stream->video_out,
this->width, this->height, this->aspect,
XINE_IMGFMT_DXR3, VO_BOTH_FIELDS);
img->pts = buf->pts;
@@ -364,7 +409,7 @@ static void dxr3_decode_data(video_decoder_t *this_gen, buf_element_t *buf)
/* we have had enough skipping messages now, let's react */
int64_t vpts_adjust = skip * (int64_t)img->duration / 2;
if (vpts_adjust > 90000) vpts_adjust = 90000;
- this->xine->metronom->set_option(this->xine->metronom,
+ this->stream->metronom->set_option(this->stream->metronom,
METRONOM_ADJ_VPTS_OFFSET, vpts_adjust);
this->skip_count = 0;
this->resync_window = 0;
@@ -408,7 +453,7 @@ static void dxr3_decode_data(video_decoder_t *this_gen, buf_element_t *buf)
*/
if (this->fd_video < 0) {
char tmpstr[128];
- snprintf (tmpstr, sizeof(tmpstr), "%s_mv%s", this->devname, this->devnum);
+ snprintf (tmpstr, sizeof(tmpstr), "%s_mv%s", this->class->devname, this->class->devnum);
if ((this->fd_video = open(tmpstr, O_WRONLY | O_NONBLOCK)) < 0) {
printf("dxr3_decode_video: Failed to open video device %s (%s)\n",
tmpstr, strerror(errno));
@@ -426,14 +471,13 @@ static void dxr3_decode_data(video_decoder_t *this_gen, buf_element_t *buf)
if (!this->scr) {
int64_t time;
- time = this->xine->metronom->get_current_time(
- this->xine->metronom);
+ time = this->stream->metronom->get_current_time(this->stream->metronom);
- this->scr = dxr3_scr_init(this->xine);
+ this->scr = dxr3_scr_init(this->stream);
this->scr->scr_plugin.start(&this->scr->scr_plugin, time);
- this->xine->metronom->register_scr(
- this->xine->metronom, &this->scr->scr_plugin);
- if (this->xine->metronom->scr_master == &this->scr->scr_plugin)
+ this->stream->metronom->register_scr(
+ this->stream->metronom, &this->scr->scr_plugin);
+ if (this->stream->metronom->scr_master == &this->scr->scr_plugin)
#if LOG_VID
printf("dxr3_decode_video: dxr3_scr plugin is master\n");
#endif
@@ -447,8 +491,8 @@ static void dxr3_decode_data(video_decoder_t *this_gen, buf_element_t *buf)
if (vpts) {
int64_t delay;
- delay = vpts - this->xine->metronom->get_current_time(
- this->xine->metronom);
+ delay = vpts - this->stream->metronom->get_current_time(
+ this->stream->metronom);
#if LOG_PTS
printf("dxr3_decode_video: SETPTS got %lld\n", vpts);
#endif
@@ -493,6 +537,10 @@ static void dxr3_decode_data(video_decoder_t *this_gen, buf_element_t *buf)
written, buf->size);
}
+static void dxr3_reset(video_decoder_t *this_gen)
+{
+}
+
static void dxr3_flush(video_decoder_t *this_gen)
{
dxr3_decoder_t *this = (dxr3_decoder_t *)this_gen;
@@ -500,14 +548,10 @@ static void dxr3_flush(video_decoder_t *this_gen)
if (this->fd_video >= 0) fsync(this->fd_video);
}
-static void dxr3_reset(video_decoder_t *this_gen)
-{
-}
-
-static void dxr3_close(video_decoder_t *this_gen)
+static void dxr3_dispose(video_decoder_t *this_gen)
{
dxr3_decoder_t *this = (dxr3_decoder_t *)this_gen;
- metronom_t *metronom = this->xine->metronom;
+ metronom_t *metronom = this->stream->metronom;
if (this->scr) {
metronom->unregister_scr(metronom, &this->scr->scr_plugin);
@@ -518,30 +562,33 @@ static void dxr3_close(video_decoder_t *this_gen)
if (this->fd_video >= 0) close(this->fd_video);
this->fd_video = -1;
- this->video_out->close(this->video_out);
+ this->stream->video_out->close(this->stream->video_out);
this->have_header_info = 0;
-}
-
-static void dxr3_dispose(video_decoder_t *this_gen)
-{
- free(this_gen);
+ this->class->instance = 0;
+
+ free(this);
}
-static int dxr3_present(xine_t *xine)
+static int dxr3_present(xine_stream_t *stream)
{
- int info;
-
- if (xine && xine->video_driver) {
- info = xine->video_driver->get_property(xine->video_driver, VO_PROP_VO_TYPE);
+ 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);
+ }
+ }
#ifdef LOG_VID
- printf("dxr3_decode_video: dxr3 presence test: info = %d\n", info);
+ printf("dxr3_decode_video: dxr3 %s\n", present ? "present" : "not present");
#endif
- if ((info != VO_TYPE_DXR3_LETTERBOXED) && (info != VO_TYPE_DXR3_WIDE))
- return 0;
- }
- return 1;
+ return present;
}
static int dxr3_mvcommand(int fd_control, int command)
@@ -575,32 +622,36 @@ static void parse_mpeg_header(dxr3_decoder_t *this, uint8_t * buffer)
(this->last_width != this->width) ||
(this->last_height != this->height) ||
(this->last_aspect != this->aspect)) {
- xine_frame_change_event_t event;
- event.event.type = XINE_EVENT_FRAME_CHANGE;
- event.width = this->width;
- event.height = this->height;
- event.aspect = this->aspect;
- xine_send_event(this->xine, &event.event);
+ xine_event_t event;
+ xine_format_change_data_t data;
+ event.type = XINE_EVENT_FRAME_FORMAT_CHANGE;
+ event.stream = this->stream;
+ event.data = &data;
+ event.data_length = sizeof(data);
+ data.width = this->width;
+ data.height = this->height;
+ data.aspect = this->aspect;
+ xine_event_send(this->stream, &event);
this->last_width = this->width;
this->last_height = this->height;
this->last_aspect = this->aspect;
/* update stream metadata */
- this->xine->stream_info[XINE_STREAM_INFO_VIDEO_WIDTH] = this->width;
- this->xine->stream_info[XINE_STREAM_INFO_VIDEO_HEIGHT] = this->height;
+ this->stream->stream_info[XINE_STREAM_INFO_VIDEO_WIDTH] = this->width;
+ this->stream->stream_info[XINE_STREAM_INFO_VIDEO_HEIGHT] = this->height;
switch (this->aspect) {
case XINE_VO_ASPECT_SQUARE:
- this->xine->stream_info[XINE_STREAM_INFO_VIDEO_RATIO] = 10000;
+ this->stream->stream_info[XINE_STREAM_INFO_VIDEO_RATIO] = 10000;
break;
case XINE_VO_ASPECT_4_3:
- this->xine->stream_info[XINE_STREAM_INFO_VIDEO_RATIO] = 10000 * 4.0 / 3.0;
+ this->stream->stream_info[XINE_STREAM_INFO_VIDEO_RATIO] = 10000 * 4.0 / 3.0;
break;
case XINE_VO_ASPECT_PAN_SCAN:
case XINE_VO_ASPECT_ANAMORPHIC:
- this->xine->stream_info[XINE_STREAM_INFO_VIDEO_RATIO] = 10000 * 16.0 / 9.0;
+ this->stream->stream_info[XINE_STREAM_INFO_VIDEO_RATIO] = 10000 * 16.0 / 9.0;
break;
case XINE_VO_ASPECT_DVB:
- this->xine->stream_info[XINE_STREAM_INFO_VIDEO_RATIO] = 10000 * 2.11;
+ this->stream->stream_info[XINE_STREAM_INFO_VIDEO_RATIO] = 10000 * 2.11;
break;
}
}
@@ -643,7 +694,7 @@ static int get_duration(dxr3_decoder_t *this)
}
/* update stream metadata */
- this->xine->stream_info[XINE_STREAM_INFO_FRAME_DURATION] = duration;
+ this->stream->stream_info[XINE_STREAM_INFO_FRAME_DURATION] = duration;
if (this->correct_durations) {
/* we set an initial average frame duration here */
@@ -656,13 +707,13 @@ static int get_duration(dxr3_decoder_t *this)
*/
if (this->avg_duration && this->avg_duration < 3300 && duration == 3600) {
if (this->force_duration_window > 0) {
- // we are already in a force_duration window, so we force duration
+ /* we are already in a force_duration window, so we force duration */
this->force_duration_window = FORCE_DURATION_WINDOW_SIZE;
return 3000;
}
if (this->force_duration_window <= 0 && (this->force_duration_window += 10) > 0) {
- // we just entered a force_duration window, so we start the correction
- metronom_t *metronom = this->xine->metronom;
+ /* we just entered a force_duration window, so we start the correction */
+ metronom_t *metronom = this->stream->metronom;
int64_t cur_offset;
printf("dxr3_decode_video: WARNING: correcting frame rate code from PAL to NTSC\n");
/* those weird streams need an offset, too */
@@ -674,11 +725,11 @@ static int get_duration(dxr3_decoder_t *this)
}
if (this->force_duration_window == -FORCE_DURATION_WINDOW_SIZE)
- // we are far from a force_duration window
+ /* we are far from a force_duration window */
return duration;
if (--this->force_duration_window == 0) {
- // we have just left a force_duration window
- metronom_t *metronom = this->xine->metronom;
+ /* we have just left a force_duration window */
+ metronom_t *metronom = this->stream->metronom;
int64_t cur_offset;
cur_offset = metronom->get_option(metronom, METRONOM_AV_OFFSET);
metronom->set_option(metronom, METRONOM_AV_OFFSET, cur_offset + 28800);