Browse Source

V4L/DVB: pvrusb2: Enforce a 300msec stabilization interval during stream strart

Martin Dauskardt <martin.dauskardt@gmx.de> has determined that the
encoder has a much better chance of starting cleanly if we
deliberately hold off starting it util the video digitizer has had a
chance to run for at least 300msec first.  These changes implement an
enforced 300msec wait in the state machine that orchestrates streaming
start / stop.

Signed-off-by: Mike Isely <isely@pobox.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Mike Isely 15 years ago
parent
commit
6e9313755a

+ 10 - 2
drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h

@@ -233,8 +233,9 @@ struct pvr2_hdw {
 	int state_encoder_waitok;     /* Encoder pre-wait done */
 	int state_encoder_runok;      /* Encoder has run for >= .25 sec */
 	int state_decoder_run;        /* Decoder is running */
+	int state_decoder_ready;      /* Decoder is stabilized & streamable */
 	int state_usbstream_run;      /* FX2 is streaming */
-	int state_decoder_quiescent;  /* Decoder idle for > 50msec */
+	int state_decoder_quiescent;  /* Decoder idle for minimal interval */
 	int state_pipeline_config;    /* Pipeline is configured */
 	int state_pipeline_req;       /* Somebody wants to stream */
 	int state_pipeline_pause;     /* Pipeline must be paused */
@@ -255,9 +256,16 @@ struct pvr2_hdw {
 	void (*state_func)(void *);
 	void *state_data;
 
-	/* Timer for measuring decoder settling time */
+	/* Timer for measuring required decoder settling time before we're
+	   allowed to fire it up again. */
 	struct timer_list quiescent_timer;
 
+	/* Timer for measuring decoder stabilization time, which is the
+	   amount of time we need to let the decoder run before we can
+	   trust its output (otherwise the encoder might see garbage and
+	   then fail to start correctly). */
+	struct timer_list decoder_stabilization_timer;
+
 	/* Timer for measuring encoder pre-wait time */
 	struct timer_list encoder_wait_timer;
 

+ 38 - 3
drivers/media/video/pvrusb2/pvrusb2-hdw.c

@@ -48,6 +48,10 @@
    before we are allowed to start it running. */
 #define TIME_MSEC_DECODER_WAIT 50
 
+/* This defines a minimum interval that the decoder must be allowed to run
+   before we can safely begin using its streaming output. */
+#define TIME_MSEC_DECODER_STABILIZATION_WAIT 300
+
 /* This defines a minimum interval that the encoder must remain quiet
    before we are allowed to configure it.  I had this originally set to
    50msec, but Martin Dauskardt <martin.dauskardt@gmx.de> reports that
@@ -334,6 +338,7 @@ static int pvr2_hdw_get_eeprom_addr(struct pvr2_hdw *hdw);
 static void pvr2_hdw_internal_find_stdenum(struct pvr2_hdw *hdw);
 static void pvr2_hdw_internal_set_std_avail(struct pvr2_hdw *hdw);
 static void pvr2_hdw_quiescent_timeout(unsigned long);
+static void pvr2_hdw_decoder_stabilization_timeout(unsigned long);
 static void pvr2_hdw_encoder_wait_timeout(unsigned long);
 static void pvr2_hdw_encoder_run_timeout(unsigned long);
 static int pvr2_issue_simple_cmd(struct pvr2_hdw *,u32);
@@ -2462,6 +2467,11 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
 	hdw->quiescent_timer.data = (unsigned long)hdw;
 	hdw->quiescent_timer.function = pvr2_hdw_quiescent_timeout;
 
+	init_timer(&hdw->decoder_stabilization_timer);
+	hdw->decoder_stabilization_timer.data = (unsigned long)hdw;
+	hdw->decoder_stabilization_timer.function =
+		pvr2_hdw_decoder_stabilization_timeout;
+
 	init_timer(&hdw->encoder_wait_timer);
 	hdw->encoder_wait_timer.data = (unsigned long)hdw;
 	hdw->encoder_wait_timer.function = pvr2_hdw_encoder_wait_timeout;
@@ -2675,6 +2685,7 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
  fail:
 	if (hdw) {
 		del_timer_sync(&hdw->quiescent_timer);
+		del_timer_sync(&hdw->decoder_stabilization_timer);
 		del_timer_sync(&hdw->encoder_run_timer);
 		del_timer_sync(&hdw->encoder_wait_timer);
 		if (hdw->workqueue) {
@@ -2742,6 +2753,7 @@ void pvr2_hdw_destroy(struct pvr2_hdw *hdw)
 		hdw->workqueue = NULL;
 	}
 	del_timer_sync(&hdw->quiescent_timer);
+	del_timer_sync(&hdw->decoder_stabilization_timer);
 	del_timer_sync(&hdw->encoder_run_timer);
 	del_timer_sync(&hdw->encoder_wait_timer);
 	if (hdw->fw_buffer) {
@@ -4453,7 +4465,7 @@ static int state_check_enable_encoder_run(struct pvr2_hdw *hdw)
 
 	switch (hdw->pathway_state) {
 	case PVR2_PATHWAY_ANALOG:
-		if (hdw->state_decoder_run) {
+		if (hdw->state_decoder_run && hdw->state_decoder_ready) {
 			/* In analog mode, if the decoder is running, then
 			   run the encoder. */
 			return !0;
@@ -4520,6 +4532,17 @@ static void pvr2_hdw_quiescent_timeout(unsigned long data)
 }
 
 
+/* Timeout function for decoder stabilization timer. */
+static void pvr2_hdw_decoder_stabilization_timeout(unsigned long data)
+{
+	struct pvr2_hdw *hdw = (struct pvr2_hdw *)data;
+	hdw->state_decoder_ready = !0;
+	trace_stbit("state_decoder_ready", hdw->state_decoder_ready);
+	hdw->state_stale = !0;
+	queue_work(hdw->workqueue, &hdw->workpoll);
+}
+
+
 /* Timeout function for encoder wait timer. */
 static void pvr2_hdw_encoder_wait_timeout(unsigned long data)
 {
@@ -4558,8 +4581,13 @@ static int state_eval_decoder_run(struct pvr2_hdw *hdw)
 		}
 		hdw->state_decoder_quiescent = 0;
 		hdw->state_decoder_run = 0;
-		/* paranoia - solve race if timer just completed */
+		/* paranoia - solve race if timer(s) just completed */
 		del_timer_sync(&hdw->quiescent_timer);
+		/* Kill the stabilization timer, in case we're killing the
+		   encoder before the previous stabilization interval has
+		   been properly timed. */
+		del_timer_sync(&hdw->decoder_stabilization_timer);
+		hdw->state_decoder_ready = 0;
 	} else {
 		if (!hdw->state_decoder_quiescent) {
 			if (!timer_pending(&hdw->quiescent_timer)) {
@@ -4597,10 +4625,16 @@ static int state_eval_decoder_run(struct pvr2_hdw *hdw)
 		if (hdw->flag_decoder_missed) return 0;
 		if (pvr2_decoder_enable(hdw,!0) < 0) return 0;
 		hdw->state_decoder_quiescent = 0;
+		hdw->state_decoder_ready = 0;
 		hdw->state_decoder_run = !0;
+		hdw->decoder_stabilization_timer.expires =
+			jiffies +
+			(HZ * TIME_MSEC_DECODER_STABILIZATION_WAIT / 1000);
+		add_timer(&hdw->decoder_stabilization_timer);
 	}
 	trace_stbit("state_decoder_quiescent",hdw->state_decoder_quiescent);
 	trace_stbit("state_decoder_run",hdw->state_decoder_run);
+	trace_stbit("state_decoder_ready", hdw->state_decoder_ready);
 	return !0;
 }
 
@@ -4798,7 +4832,8 @@ static unsigned int pvr2_hdw_report_unlocked(struct pvr2_hdw *hdw,int which,
 			buf,acnt,
 			"worker:%s%s%s%s%s%s%s",
 			(hdw->state_decoder_run ?
-			 " <decode:run>" :
+			 (hdw->state_decoder_ready ?
+			  "<decode:run>" : " <decode:start>") :
 			 (hdw->state_decoder_quiescent ?
 			  "" : " <decode:stop>")),
 			(hdw->state_decoder_quiescent ?

+ 1 - 0
drivers/media/video/pvrusb2/pvrusb2-hdw.h

@@ -306,6 +306,7 @@ struct pvr2_hdw_debug_info {
 	int state_encoder_ok;
 	int state_encoder_run;
 	int state_decoder_run;
+	int state_decoder_ready;
 	int state_usbstream_run;
 	int state_decoder_quiescent;
 	int state_pipeline_config;