|
@@ -246,34 +246,40 @@ static int ivtv_validate_speed(int cur_speed, int new_speed)
|
|
|
}
|
|
|
|
|
|
static int ivtv_video_command(struct ivtv *itv, struct ivtv_open_id *id,
|
|
|
- struct video_command *vc, int try)
|
|
|
+ struct v4l2_decoder_cmd *dc, int try)
|
|
|
{
|
|
|
struct ivtv_stream *s = &itv->streams[IVTV_DEC_STREAM_TYPE_MPG];
|
|
|
|
|
|
if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
|
|
|
return -EINVAL;
|
|
|
|
|
|
- switch (vc->cmd) {
|
|
|
- case VIDEO_CMD_PLAY: {
|
|
|
- vc->flags = 0;
|
|
|
- vc->play.speed = ivtv_validate_speed(itv->speed, vc->play.speed);
|
|
|
- if (vc->play.speed < 0)
|
|
|
- vc->play.format = VIDEO_PLAY_FMT_GOP;
|
|
|
+ switch (dc->cmd) {
|
|
|
+ case V4L2_DEC_CMD_START: {
|
|
|
+ dc->flags &= V4L2_DEC_CMD_START_MUTE_AUDIO;
|
|
|
+ dc->start.speed = ivtv_validate_speed(itv->speed, dc->start.speed);
|
|
|
+ if (dc->start.speed < 0)
|
|
|
+ dc->start.format = V4L2_DEC_START_FMT_GOP;
|
|
|
+ else
|
|
|
+ dc->start.format = V4L2_DEC_START_FMT_NONE;
|
|
|
+ if (dc->start.speed != 500 && dc->start.speed != 1500)
|
|
|
+ dc->flags = dc->start.speed == 1000 ? 0 :
|
|
|
+ V4L2_DEC_CMD_START_MUTE_AUDIO;
|
|
|
if (try) break;
|
|
|
|
|
|
+ itv->speed_mute_audio = dc->flags & V4L2_DEC_CMD_START_MUTE_AUDIO;
|
|
|
if (ivtv_set_output_mode(itv, OUT_MPG) != OUT_MPG)
|
|
|
return -EBUSY;
|
|
|
if (test_and_clear_bit(IVTV_F_I_DEC_PAUSED, &itv->i_flags)) {
|
|
|
/* forces ivtv_set_speed to be called */
|
|
|
itv->speed = 0;
|
|
|
}
|
|
|
- return ivtv_start_decoding(id, vc->play.speed);
|
|
|
+ return ivtv_start_decoding(id, dc->start.speed);
|
|
|
}
|
|
|
|
|
|
- case VIDEO_CMD_STOP:
|
|
|
- vc->flags &= VIDEO_CMD_STOP_IMMEDIATELY|VIDEO_CMD_STOP_TO_BLACK;
|
|
|
- if (vc->flags & VIDEO_CMD_STOP_IMMEDIATELY)
|
|
|
- vc->stop.pts = 0;
|
|
|
+ case V4L2_DEC_CMD_STOP:
|
|
|
+ dc->flags &= V4L2_DEC_CMD_STOP_IMMEDIATELY | V4L2_DEC_CMD_STOP_TO_BLACK;
|
|
|
+ if (dc->flags & V4L2_DEC_CMD_STOP_IMMEDIATELY)
|
|
|
+ dc->stop.pts = 0;
|
|
|
if (try) break;
|
|
|
if (atomic_read(&itv->decoding) == 0)
|
|
|
return 0;
|
|
@@ -281,22 +287,22 @@ static int ivtv_video_command(struct ivtv *itv, struct ivtv_open_id *id,
|
|
|
return -EBUSY;
|
|
|
|
|
|
itv->output_mode = OUT_NONE;
|
|
|
- return ivtv_stop_v4l2_decode_stream(s, vc->flags, vc->stop.pts);
|
|
|
+ return ivtv_stop_v4l2_decode_stream(s, dc->flags, dc->stop.pts);
|
|
|
|
|
|
- case VIDEO_CMD_FREEZE:
|
|
|
- vc->flags &= VIDEO_CMD_FREEZE_TO_BLACK;
|
|
|
+ case V4L2_DEC_CMD_PAUSE:
|
|
|
+ dc->flags &= V4L2_DEC_CMD_PAUSE_TO_BLACK;
|
|
|
if (try) break;
|
|
|
if (itv->output_mode != OUT_MPG)
|
|
|
return -EBUSY;
|
|
|
if (atomic_read(&itv->decoding) > 0) {
|
|
|
ivtv_vapi(itv, CX2341X_DEC_PAUSE_PLAYBACK, 1,
|
|
|
- (vc->flags & VIDEO_CMD_FREEZE_TO_BLACK) ? 1 : 0);
|
|
|
+ (dc->flags & V4L2_DEC_CMD_PAUSE_TO_BLACK) ? 1 : 0);
|
|
|
set_bit(IVTV_F_I_DEC_PAUSED, &itv->i_flags);
|
|
|
}
|
|
|
break;
|
|
|
|
|
|
- case VIDEO_CMD_CONTINUE:
|
|
|
- vc->flags = 0;
|
|
|
+ case V4L2_DEC_CMD_RESUME:
|
|
|
+ dc->flags = 0;
|
|
|
if (try) break;
|
|
|
if (itv->output_mode != OUT_MPG)
|
|
|
return -EBUSY;
|
|
@@ -1575,6 +1581,24 @@ static int ivtv_log_status(struct file *file, void *fh)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+static int ivtv_decoder_cmd(struct file *file, void *fh, struct v4l2_decoder_cmd *dec)
|
|
|
+{
|
|
|
+ struct ivtv_open_id *id = fh2id(file->private_data);
|
|
|
+ struct ivtv *itv = id->itv;
|
|
|
+
|
|
|
+ IVTV_DEBUG_IOCTL("VIDIOC_DECODER_CMD %d\n", dec->cmd);
|
|
|
+ return ivtv_video_command(itv, id, dec, false);
|
|
|
+}
|
|
|
+
|
|
|
+static int ivtv_try_decoder_cmd(struct file *file, void *fh, struct v4l2_decoder_cmd *dec)
|
|
|
+{
|
|
|
+ struct ivtv_open_id *id = fh2id(file->private_data);
|
|
|
+ struct ivtv *itv = id->itv;
|
|
|
+
|
|
|
+ IVTV_DEBUG_IOCTL("VIDIOC_TRY_DECODER_CMD %d\n", dec->cmd);
|
|
|
+ return ivtv_video_command(itv, id, dec, true);
|
|
|
+}
|
|
|
+
|
|
|
static int ivtv_decoder_ioctls(struct file *filp, unsigned int cmd, void *arg)
|
|
|
{
|
|
|
struct ivtv_open_id *id = fh2id(filp->private_data);
|
|
@@ -1669,52 +1693,54 @@ static int ivtv_decoder_ioctls(struct file *filp, unsigned int cmd, void *arg)
|
|
|
}
|
|
|
|
|
|
case VIDEO_PLAY: {
|
|
|
- struct video_command vc;
|
|
|
+ struct v4l2_decoder_cmd dc;
|
|
|
|
|
|
IVTV_DEBUG_IOCTL("VIDEO_PLAY\n");
|
|
|
- memset(&vc, 0, sizeof(vc));
|
|
|
- vc.cmd = VIDEO_CMD_PLAY;
|
|
|
- return ivtv_video_command(itv, id, &vc, 0);
|
|
|
+ memset(&dc, 0, sizeof(dc));
|
|
|
+ dc.cmd = V4L2_DEC_CMD_START;
|
|
|
+ return ivtv_video_command(itv, id, &dc, 0);
|
|
|
}
|
|
|
|
|
|
case VIDEO_STOP: {
|
|
|
- struct video_command vc;
|
|
|
+ struct v4l2_decoder_cmd dc;
|
|
|
|
|
|
IVTV_DEBUG_IOCTL("VIDEO_STOP\n");
|
|
|
- memset(&vc, 0, sizeof(vc));
|
|
|
- vc.cmd = VIDEO_CMD_STOP;
|
|
|
- vc.flags = VIDEO_CMD_STOP_TO_BLACK | VIDEO_CMD_STOP_IMMEDIATELY;
|
|
|
- return ivtv_video_command(itv, id, &vc, 0);
|
|
|
+ memset(&dc, 0, sizeof(dc));
|
|
|
+ dc.cmd = V4L2_DEC_CMD_STOP;
|
|
|
+ dc.flags = V4L2_DEC_CMD_STOP_TO_BLACK | V4L2_DEC_CMD_STOP_IMMEDIATELY;
|
|
|
+ return ivtv_video_command(itv, id, &dc, 0);
|
|
|
}
|
|
|
|
|
|
case VIDEO_FREEZE: {
|
|
|
- struct video_command vc;
|
|
|
+ struct v4l2_decoder_cmd dc;
|
|
|
|
|
|
IVTV_DEBUG_IOCTL("VIDEO_FREEZE\n");
|
|
|
- memset(&vc, 0, sizeof(vc));
|
|
|
- vc.cmd = VIDEO_CMD_FREEZE;
|
|
|
- return ivtv_video_command(itv, id, &vc, 0);
|
|
|
+ memset(&dc, 0, sizeof(dc));
|
|
|
+ dc.cmd = V4L2_DEC_CMD_PAUSE;
|
|
|
+ return ivtv_video_command(itv, id, &dc, 0);
|
|
|
}
|
|
|
|
|
|
case VIDEO_CONTINUE: {
|
|
|
- struct video_command vc;
|
|
|
+ struct v4l2_decoder_cmd dc;
|
|
|
|
|
|
IVTV_DEBUG_IOCTL("VIDEO_CONTINUE\n");
|
|
|
- memset(&vc, 0, sizeof(vc));
|
|
|
- vc.cmd = VIDEO_CMD_CONTINUE;
|
|
|
- return ivtv_video_command(itv, id, &vc, 0);
|
|
|
+ memset(&dc, 0, sizeof(dc));
|
|
|
+ dc.cmd = V4L2_DEC_CMD_RESUME;
|
|
|
+ return ivtv_video_command(itv, id, &dc, 0);
|
|
|
}
|
|
|
|
|
|
case VIDEO_COMMAND:
|
|
|
case VIDEO_TRY_COMMAND: {
|
|
|
- struct video_command *vc = arg;
|
|
|
+ /* Note: struct v4l2_decoder_cmd has the same layout as
|
|
|
+ struct video_command */
|
|
|
+ struct v4l2_decoder_cmd *dc = arg;
|
|
|
int try = (cmd == VIDEO_TRY_COMMAND);
|
|
|
|
|
|
if (try)
|
|
|
- IVTV_DEBUG_IOCTL("VIDEO_TRY_COMMAND %d\n", vc->cmd);
|
|
|
+ IVTV_DEBUG_IOCTL("VIDEO_TRY_COMMAND %d\n", dc->cmd);
|
|
|
else
|
|
|
- IVTV_DEBUG_IOCTL("VIDEO_COMMAND %d\n", vc->cmd);
|
|
|
- return ivtv_video_command(itv, id, vc, try);
|
|
|
+ IVTV_DEBUG_IOCTL("VIDEO_COMMAND %d\n", dc->cmd);
|
|
|
+ return ivtv_video_command(itv, id, dc, try);
|
|
|
}
|
|
|
|
|
|
case VIDEO_GET_EVENT: {
|
|
@@ -1892,6 +1918,8 @@ static const struct v4l2_ioctl_ops ivtv_ioctl_ops = {
|
|
|
.vidioc_enum_fmt_vid_cap = ivtv_enum_fmt_vid_cap,
|
|
|
.vidioc_encoder_cmd = ivtv_encoder_cmd,
|
|
|
.vidioc_try_encoder_cmd = ivtv_try_encoder_cmd,
|
|
|
+ .vidioc_decoder_cmd = ivtv_decoder_cmd,
|
|
|
+ .vidioc_try_decoder_cmd = ivtv_try_decoder_cmd,
|
|
|
.vidioc_enum_fmt_vid_out = ivtv_enum_fmt_vid_out,
|
|
|
.vidioc_g_fmt_vid_cap = ivtv_g_fmt_vid_cap,
|
|
|
.vidioc_g_fmt_vbi_cap = ivtv_g_fmt_vbi_cap,
|