Mailing List archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[mpeg2] Re: Setting Audio, Video, and PCR PIDs



> > After this change, things are working, but I still have a little
> > problem: in my setup, I first run a program that opens /dev/video1, does
> > some ioctl() to configure the stream, and exits; then I run a different
> > program that opens /dev/video1 for reading. With your patch, this does
> > not work because when the second program starts to read from /dev/video1
> > saa6752hs_init() is called with params == NULL, hence it restores all
> > the parameters to the default. I think that adding a
> > i2c_set_clientdata(client, cachedParams);
> > at the end of saa6752hs_init() fixes this problem (at least, it works
> > for me, but I don't know if it is the correct thing to do -- I do not
> > know the i2c stuff well).
>
> Hmm, its supposed to be able to support that (I do something similar). When
> its called with (params!=NULL), it copies them into the cachedParams. When
> its called with (params==NULL), it just uses the cachedParams, as set by
> the previous call. Must be an annoying bug somewhere - I'll see if I can
> spot it.

Hi, found a problem - I had the check for target bitrate and max bit rate the 
wrong way round.

Oh, I've also added in that printk we were talking about - moan if 
MPEG_SETPARAMS fails since we send the return code to the user app.

Just tested it with a quick program - seems to be preserving the mpeg settings 
across multiple open() calls now.
Common subdirectories: saa7134-0.2.12.orig/.tmp_versions and saa7134-0.2.12/.tmp_versions
Common subdirectories: saa7134-0.2.12.orig/doc and saa7134-0.2.12/doc
Common subdirectories: saa7134-0.2.12.orig/linux and saa7134-0.2.12/linux
Common subdirectories: saa7134-0.2.12.orig/media and saa7134-0.2.12/media
diff -Nau saa7134-0.2.12.orig/saa6752hs.c saa7134-0.2.12/saa6752hs.c
--- saa7134-0.2.12.orig/saa6752hs.c	2004-02-22 01:59:35.000000000 +0000
+++ saa7134-0.2.12/saa6752hs.c	2004-05-17 16:07:44.454938784 +0100
@@ -11,6 +11,7 @@
 #include <linux/types.h>
 #include <linux/videodev.h>
 #include <linux/init.h>
+#include <linux/crc32.h>
 
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
 #include "i2c-compat.h"
@@ -73,9 +74,9 @@
 
 	0x00, 0x01, // program_number(1)
 	
-	0xe0, 0x10, // PMT PID(0x10)
+	0xe0, 0x00, // PMT PID
 
-	0x76, 0xf1, 0x44, 0xd1 // CRC32
+	0x00, 0x00, 0x00, 0x00 // CRC32
 };
 
 static u8 PMT[] = {
@@ -83,7 +84,7 @@
 	0x01, // table number for encoder
   
 	0x47, // sync
-	0x40, 0x10, // transport_error_indicator(0), payload_unit_start(1), transport_priority(0), pid(0x10)
+	0x40, 0x00, // transport_error_indicator(0), payload_unit_start(1), transport_priority(0), pid
 	0x10, // transport_scrambling_control(00), adaptation_field_control(01), continuity_counter(0)
      
 	0x00, // PSI pointer to start of table
@@ -97,22 +98,27 @@
     
 	0x00, 0x00, // section_number(0), last_section_number(0)
     
-	0xe1, 0x04, // PCR_PID (0x104)
+	0xe0, 0x00, // PCR_PID
    
 	0xf0, 0x00, // program_info_length(0)
     
-	0x02, 0xe1, 0x00, 0xf0, 0x00, // video stream type(2), pid(0x100)
-	0x04, 0xe1, 0x03, 0xf0, 0x00, // audio stream type(4), pid(0x103)
+	0x02, 0xe0, 0x00, 0xf0, 0x00, // video stream type(2), pid
+	0x04, 0xe0, 0x00, 0xf0, 0x00, // audio stream type(4), pid
     
-	0xa1, 0xca, 0x0f, 0x82 // CRC32
+	0x00, 0x00, 0x00, 0x00 // CRC32
 };
 
 static struct mpeg_params mpeg_params_template =
 {
-	.bitrate_mode = MPEG_BITRATE_MODE_CBR,
-	.video_target_bitrate = 5000,
+	.video_bitrate_mode = MPEG_VIDEO_BITRATE_MODE_VBR,
+	.video_target_bitrate = 4000,
+     	.video_max_bitrate = 6000,
 	.audio_bitrate = MPEG_AUDIO_BITRATE_256,
-	.total_bitrate = 6000,
+	.total_bitrate = 7000,
+	.pmt_pid = 16,
+	.video_pid = 260,
+	.audio_pid = 256,
+	.pcr_pid = 259,
 };
 
   
@@ -133,7 +139,7 @@
 		break;
 	  
 	case SAA6752HS_COMMAND_STOP:
-		  	buf[0] = 0x03;
+		buf[0] = 0x03;
 		break;
 	  
 	case SAA6752HS_COMMAND_START:
@@ -197,11 +203,11 @@
   
 	// set the bitrate mode
 	buf[0] = 0x71;
-	buf[1] = params->bitrate_mode;
+	buf[1] = params->video_bitrate_mode;
 	i2c_master_send(client, buf, 2);
 	  
 	// set the video bitrate
-	if (params->bitrate_mode == MPEG_BITRATE_MODE_VBR) {
+	if (params->video_bitrate_mode == MPEG_VIDEO_BITRATE_MODE_VBR) {
 		// set the target bitrate
 		buf[0] = 0x80;
 	    	buf[1] = params->video_target_bitrate >> 8;
@@ -239,25 +245,73 @@
 static int saa6752hs_init(struct i2c_client* client, struct mpeg_params* params)
 {  
 	unsigned char buf[3];
-	void *data;
+	struct mpeg_params* cachedParams;
+	u32 crc;
+	unsigned char localPAT[256];
+   	unsigned char localPMT[256];
+
+	// grab the previous set of parameters
+	cachedParams = (struct mpeg_params*) i2c_get_clientdata(client);
 
 	// check the bitrate parameters first
 	if (params != NULL) {
-		if (params->bitrate_mode >= MPEG_BITRATE_MODE_MAX)
+		unsigned int pmt_pid = 0, pcr_pid = 0, video_pid = 0 , audio_pid = 0;
+
+	   	// check supplied params are valid
+		if (params->video_bitrate_mode >= MPEG_VIDEO_BITRATE_MODE_MAX)
 			return -EINVAL;
 		if (params->video_target_bitrate >= MPEG_VIDEO_TARGET_BITRATE_MAX)
 			return -EINVAL;
-  		if (params->video_max_bitrate >= MPEG_VIDEO_MAX_BITRATE_MAX)
-			return -EINVAL;
 		if (params->audio_bitrate >= MPEG_AUDIO_BITRATE_MAX)
 			return -EINVAL;
 		if (params->total_bitrate >= MPEG_TOTAL_BITRATE_MAX)
         		return -EINVAL;
-		if (params->bitrate_mode         == MPEG_BITRATE_MODE_MAX &&
-		    params->video_target_bitrate <= params->video_max_bitrate)
-			return -EINVAL; 
+		if (params->video_bitrate_mode == MPEG_VIDEO_BITRATE_MODE_VBR) {
+			if (params->video_max_bitrate >= MPEG_VIDEO_MAX_BITRATE_MAX)
+				return -EINVAL;
+			if (params->video_target_bitrate >= params->video_max_bitrate)
+				return -EINVAL;
+		}
+		if (params->pmt_pid != 0) {
+			if (params->pmt_pid > MPEG_PID_MAX)
+				return -EINVAL;
+		   	pmt_pid = params->pmt_pid;
+		} else {
+			pmt_pid = cachedParams->pmt_pid;
+		}
+		if (params->pcr_pid != 0) {
+		   	if (params->pcr_pid > MPEG_PID_MAX)
+				return -EINVAL;
+		   	pcr_pid = params->pcr_pid;
+		} else {
+			pcr_pid = cachedParams->pcr_pid;
+		}
+   		if (params->video_pid != 0) {
+		   	if (params->video_pid > MPEG_PID_MAX)
+				return -EINVAL;
+		   	video_pid = params->video_pid;
+		} else {
+			video_pid = cachedParams->video_pid;
+		}
+   		if (params->audio_pid != 0) {
+		   	if (params->audio_pid > MPEG_PID_MAX)
+				return -EINVAL;
+		   	audio_pid = params->audio_pid;
+		} else {
+			audio_pid = cachedParams->audio_pid;
+		}
+
+	   	// update cache
+   		memcpy(cachedParams, params, sizeof(struct mpeg_params));
+	   	cachedParams->pmt_pid = pmt_pid;
+   	   	cachedParams->pcr_pid = pcr_pid;
+   	   	cachedParams->video_pid = video_pid;
+   	   	cachedParams->audio_pid = audio_pid;
 	}
-  
+
+	// set bitrate
+	saa6752hs_set_bitrate(client, cachedParams);
+
     	// Set GOP structure {3, 13}
 	buf[0] = 0x72;
 	buf[1] = 0x03;
@@ -283,27 +337,55 @@
 	buf[0] = 0xB0;
 	buf[1] = 0x05;
 	i2c_master_send(client,buf,2);
-  
-    	// Set Audio PID {0x103}
+
+	/* compute PAT */
+	memcpy(localPAT, PAT, sizeof(PAT));
+	localPAT[17] = 0xe0 | ((cachedParams->pmt_pid >> 8) & 0x0f);
+	localPAT[18] = cachedParams->pmt_pid & 0xff;
+	crc = crc32_be(~0, &localPAT[7], sizeof(PAT) - 7 - 4);
+	localPAT[sizeof(PAT) - 4] = (crc >> 24) & 0xFF;
+	localPAT[sizeof(PAT) - 3] = (crc >> 16) & 0xFF;
+	localPAT[sizeof(PAT) - 2] = (crc >> 8) & 0xFF;
+	localPAT[sizeof(PAT) - 1] = crc & 0xFF;
+
+	/* compute PMT */
+      	memcpy(localPMT, PMT, sizeof(PMT));
+   	localPMT[3] = 0x40 | ((cachedParams->pmt_pid >> 8) & 0x0f);
+   	localPMT[4] = cachedParams->pmt_pid & 0xff;
+	localPMT[15] = 0xE0 | ((cachedParams->pcr_pid >> 8) & 0x0F);
+	localPMT[16] = cachedParams->pcr_pid & 0xFF;
+	localPMT[20] = 0xE0 | ((cachedParams->video_pid >> 8) & 0x0F);
+	localPMT[21] = cachedParams->video_pid & 0xFF;
+	localPMT[25] = 0xE0 | ((cachedParams->audio_pid >> 8) & 0x0F);
+	localPMT[26] = cachedParams->audio_pid & 0xFF;
+	crc = crc32_be(~0, &localPMT[7], sizeof(PMT) - 7 - 4);
+	localPMT[sizeof(PMT) - 4] = (crc >> 24) & 0xFF;
+	localPMT[sizeof(PMT) - 3] = (crc >> 16) & 0xFF;
+	localPMT[sizeof(PMT) - 2] = (crc >> 8) & 0xFF;
+	localPMT[sizeof(PMT) - 1] = crc & 0xFF;
+
+    	// Set Audio PID
 	buf[0] = 0xC1;
-	buf[1] = 0x01;
-	buf[2] = 0x03;
+	buf[1] = (cachedParams->audio_pid >> 8) & 0xFF;
+	buf[2] = cachedParams->audio_pid & 0xFF;
 	i2c_master_send(client,buf,3);
-  
-        // setup bitrate settings
-	data = i2c_get_clientdata(client);
-	if (params) {
-		saa6752hs_set_bitrate(client, params);
-		memcpy(data, params, sizeof(struct mpeg_params));
-	} else {
-		// parameters were not supplied. use the previous set
-   		saa6752hs_set_bitrate(client, (struct mpeg_params*) data);
-	}
-	  
+
+	// Set Video PID
+	buf[0] = 0xC0;
+	buf[1] = (cachedParams->video_pid >> 8) & 0xFF;
+	buf[2] = cachedParams->video_pid & 0xFF;
+	i2c_master_send(client,buf,3);
+
+ 	// Set PCR PID
+	buf[0] = 0xC4;
+	buf[1] = (cachedParams->pcr_pid >> 8) & 0xFF;
+	buf[2] = cachedParams->pcr_pid & 0xFF;
+	i2c_master_send(client,buf,3);
+
 	// Send SI tables
-  	i2c_master_send(client,PAT,sizeof(PAT));
-  	i2c_master_send(client,PMT,sizeof(PMT));
-	  
+  	i2c_master_send(client,localPAT,sizeof(PAT));
+  	i2c_master_send(client,localPMT,sizeof(PMT));
+
 	// mute then unmute audio. This removes buzzing artefacts
 	buf[0] = 0xa4;
 	buf[1] = 1;
@@ -384,10 +466,14 @@
 saa6752hs_command(struct i2c_client *client, unsigned int cmd, void *arg)
 {
 	struct mpeg_params* init_arg = arg;
+   	int result;
 
         switch (cmd) {
 	case MPEG_SETPARAMS:
-   		return saa6752hs_init(client, init_arg);
+	   	result = saa6752hs_init(client, init_arg);
+	   	if (result != 0)
+	     		printk("saa6752hs: MPEG_SETPARAMS failed: %i\n", result);
+	   	return result;
 
 	default:
 		/* nothing */
diff -Nau saa7134-0.2.12.orig/saa6752hs.h saa7134-0.2.12/saa6752hs.h
--- saa7134-0.2.12.orig/saa6752hs.h	2004-02-22 01:59:35.000000000 +0000
+++ saa7134-0.2.12/saa6752hs.h	2004-05-17 11:47:13.000000000 +0100
@@ -21,11 +21,11 @@
 #ifndef _SAA6752HS_H
 #define _SAA6752HS_H
 
-enum mpeg_bitrate_mode {
-	MPEG_BITRATE_MODE_VBR = 0, /* Variable bitrate */
-	MPEG_BITRATE_MODE_CBR = 1, /* Constant bitrate */
+enum mpeg_video_bitrate_mode {
+	MPEG_VIDEO_BITRATE_MODE_VBR = 0, /* Variable bitrate */
+	MPEG_VIDEO_BITRATE_MODE_CBR = 1, /* Constant bitrate */
 
-	MPEG_BITRATE_MODE_MAX
+	MPEG_VIDEO_BITRATE_MODE_MAX
 };
 
 enum mpeg_audio_bitrate {
@@ -38,13 +38,19 @@
 #define MPEG_VIDEO_TARGET_BITRATE_MAX 27000
 #define MPEG_VIDEO_MAX_BITRATE_MAX 27000
 #define MPEG_TOTAL_BITRATE_MAX 27000
-    
+#define MPEG_PID_MAX ((1 << 14) - 1)
+
 struct mpeg_params {
-	enum mpeg_bitrate_mode bitrate_mode;
+	enum mpeg_video_bitrate_mode video_bitrate_mode;
 	unsigned int video_target_bitrate;
 	unsigned int video_max_bitrate; // only used for VBR
 	enum mpeg_audio_bitrate audio_bitrate;
 	unsigned int total_bitrate;
+
+   	unsigned int pmt_pid;
+	unsigned int video_pid;
+	unsigned int audio_pid;
+	unsigned int pcr_pid;
 };
 
 #define MPEG_SETPARAMS             _IOW('6',100,struct mpeg_params)

Home | Main Index | Thread Index