Mailing List archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[mpeg2] Re: Setting Audio, Video, and PCR PIDs
Hi Andrew,
[...]
> We should probably use the in-kernel crc32 library...
Opss... I did not know about it ;) New patch attached. I hope I used the
kernel crc routine in the correct way - ffmpeg likes the PATs and PMTs
produced by the new code, hence it seems that the crc is computed
correctly.
> > The patch also fixes two things that I believe are typos:
> > 1) if (params->bitrate_mode == MPEG_BITRATE_MODE_MAX &&
> > params->video_target_bitrate <=
> > params->video_max_bitrate)
> > does not seem to be correct... Maybe is should be
> > if (params->bitrate_mode == MPEG_BITRATE_MODE_VBR &&
> > params->video_target_bitrate >=
> > params->video_max_bitrate)
> >
> > 2) the check on params->video_max_bitrate was performed even in the CBR
> > case
> >
> > I apologize if I misunderstood the code...
>
> Nice one! I'll have a look later; in the middle of fixing DVB stuff right now.
Ok. I noticed it because I was calling the MPEG_SETPARAMS ioctl()
without setting video_max_bitrate (I was setting bitrate_mode =
MPEG_BITRATE_MODE_CBR), and the ioctl was not working.
BTW, there is a bug that I forgot to mention: if the checks in
saa6752hs_init() fail, the ioctl() fails silently (i.e., the return
value is not negative). Since saa6752hs_init() is properly returning a
negative value, I think the problem is somewhere else... Uhm.. I think I
am seeing it: ts_init_encoder() in drivers/media/video/saa7134-ts.c is
always returning 0!!! Can we get a return value from
saa7134_i2c_call_clients()? Ok, I'll try to have a look at it...
> I have a slightly updated version with some better default bitrate parameters
> and tweaks... should I merge our two patches together & repost?
If you think that my patch is ok, that would be good.
> > Now, I am thinking about adding code for setting the video format (it is
> > currently hardcoded to D1). Is it ok to add yet another field to
> > mpeg_params?
>
> Fine by me - if you can, try and make it flexible; I was aiming for something
> that used by other MPEG encoders at a future date.
Unfortunately, I don't know about other MPEG encoders... I see that in
the saa6752hs there is a 1-byte parameter for selecting the video format
(D1, 2/3D1, 1/2D1, or SIF) and I was thinking about adding a field to
mpeg_params for setting the format. But I don't know if this is flexible
enough.
Finally, I also have a patch against saa7134-ts.c, for transforming
TS_NR_PACKETS in a module parameter (very useful for reducing the jitter
in the PCR!!!), and I wanted to submit it to Gerd Knorr, but it seems
that the v4l mailing list is not working (or I have been unsubscribed
for some reason, I don't know). I attach it to this mail; maybe you can
submit it when you will submit the next update to saa6752hs.c?
Thanks,
Luca
--
_____________________________________________________________________________
Copy this in your signature, if you think it is important:
N O W A R ! ! !
diff -urp ../linux-2.4.23/drivers/media/video/saa6752hs.c drivers/media/video/saa6752hs.c
--- ../linux-2.4.23/drivers/media/video/saa6752hs.c 2004-02-10 11:25:16.000000000 +0100
+++ drivers/media/video/saa6752hs.c 2004-05-13 13:13:56.000000000 +0200
@@ -11,6 +11,7 @@
#include <linux/types.h>
#include <linux/videodev.h>
#include <linux/init.h>
+#include <linux/crc32.h>
#include "i2c-compat.h"
#include "id.h"
@@ -233,22 +233,40 @@ static int saa6752hs_init(struct i2c_cli
{
unsigned char buf[3];
void *data;
+ u32 crc;
+ static unsigned int pcr_pid = 260, video_pid = 256 , audio_pid = 259;
// check the bitrate parameters first
if (params != NULL) {
if (params->bitrate_mode >= MPEG_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)
+ if (params->video_target_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->bitrate_mode == MPEG_BITRATE_MODE_VBR &&
+ params->video_target_bitrate >= params->video_max_bitrate)
+ return -EINVAL;
+ if (params->bitrate_mode == MPEG_BITRATE_MODE_VBR &&
+ params->video_max_bitrate >= MPEG_VIDEO_TARGET_BITRATE_MAX)
+ return -EINVAL;
+ if (params->pcr_pid != 0) {
+ if (params->pcr_pid > MPEG_PID_MAX)
+ return -EINVAL;
+ pcr_pid = params->pcr_pid;
+ }
+ if (params->video_pid != 0) {
+ if (params->video_pid > MPEG_PID_MAX)
+ return -EINVAL;
+ video_pid = params->video_pid;
+ }
+ if (params->audio_pid != 0) {
+ if (params->audio_pid > MPEG_PID_MAX)
+ return -EINVAL;
+ audio_pid = params->audio_pid;
+ }
}
// Set GOP structure {3, 13}
@@ -277,12 +295,6 @@ static int saa6752hs_init(struct i2c_cli
buf[1] = 0x05;
i2c_master_send(client,buf,2);
- // Set Audio PID {0x103}
- buf[0] = 0xC1;
- buf[1] = 0x01;
- buf[2] = 0x03;
- i2c_master_send(client,buf,3);
-
// setup bitrate settings
data = i2c_get_clientdata(client);
if (params) {
@@ -292,10 +304,44 @@ static int saa6752hs_init(struct i2c_cli
// parameters were not supplied. use the previous set
saa6752hs_set_bitrate(client, (struct mpeg_params*) data);
}
-
+
+ /* compute CRCs */
+ crc = crc32_be(~0, &PAT[7], sizeof(PAT) - 7 - 4);
+ PAT[sizeof(PAT) - 4] = (crc >> 24) & 0xFF;
+ PAT[sizeof(PAT) - 3] = (crc >> 16) & 0xFF;
+ PAT[sizeof(PAT) - 2] = (crc >> 8) & 0xFF;
+ PAT[sizeof(PAT) - 1] = crc & 0xFF;
+
+ PMT[15] = 0xE0 | ((pcr_pid >> 8) && 0x0F);
+ PMT[16] = pcr_pid & 0xFF;
+ PMT[20] = 0xE0 | ((video_pid >> 8) && 0x0F);
+ PMT[21] = video_pid & 0xFF;
+ PMT[25] = 0xE0 | ((audio_pid >> 8) && 0x0F);
+ PMT[26] = audio_pid & 0xFF;
+ crc = crc32_be(~0, &PMT[7], sizeof(PMT) - 7 - 4);
+ PMT[sizeof(PMT) - 4] = (crc >> 24) & 0xFF;
+ PMT[sizeof(PMT) - 3] = (crc >> 16) & 0xFF;
+ PMT[sizeof(PMT) - 2] = (crc >> 8) & 0xFF;
+ PMT[sizeof(PMT) - 1] = crc & 0xFF;
+ // Set Audio PID
+ buf[0] = 0xC1;
+ buf[1] = (audio_pid >> 8) & 0xFF;
+ buf[2] = audio_pid & 0xFF;
+ i2c_master_send(client,buf,3);
+ // Set Video PID
+ buf[0] = 0xC0;
+ buf[1] = (video_pid >> 8) & 0xFF;
+ buf[2] = video_pid & 0xFF;
+ i2c_master_send(client,buf,3);
+ // Set PCR PID
+ buf[0] = 0xC4;
+ buf[1] = (pcr_pid >> 8) & 0xFF;
+ buf[2] = 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,PAT,sizeof(PAT));
+ i2c_master_send(client,PMT,sizeof(PMT));
// mute then unmute audio. This removes buzzing artefacts
buf[0] = 0xa4;
diff -urp ../linux-2.4.23/drivers/media/video/saa6752hs.h drivers/media/video/saa6752hs.h
--- ../linux-2.4.23/drivers/media/video/saa6752hs.h 2004-02-10 11:25:16.000000000 +0100
+++ drivers/media/video/saa6752hs.h 2004-05-13 10:10:03.000000000 +0200
@@ -38,13 +38,17 @@ enum mpeg_audio_bitrate {
#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;
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 video_pid;
+ unsigned int audio_pid;
+ unsigned int pcr_pid;
};
#define MPEG_SETPARAMS _IOW('6',100,struct mpeg_params)
diff -urp ../linux-2.4.23/drivers/media/video/saa7134-ts.c drivers/media/video/saa7134-ts.c
--- ../linux-2.4.23/drivers/media/video/saa7134-ts.c 2004-02-10 11:25:16.000000000 +0100
+++ drivers/media/video/saa7134-ts.c 2004-05-13 10:56:54.000000000 +0200
@@ -42,7 +42,9 @@ MODULE_PARM(tsbufs,"i");
MODULE_PARM_DESC(tsbufs,"number of ts buffers, range 2-32");
#define TS_PACKET_SIZE 188 /* TS packets 188 bytes */
-#define TS_NR_PACKETS 312
+static unsigned int ts_nr_packets = 30;
+MODULE_PARM(ts_nr_packets,"i");
+MODULE_PARM_DESC(ts_nr_packets,"size of a ts buffers (in ts packets)");
#define dprintk(fmt, arg...) if (ts_debug) \
printk(KERN_DEBUG "%s/ts: " fmt, dev->name , ## arg)
@@ -96,7 +98,7 @@ static int buffer_prepare(struct file *f
dprintk("buffer_prepare [%p,%s]\n",buf,v4l2_field_names[field]);
llength = TS_PACKET_SIZE;
- lines = TS_NR_PACKETS;
+ lines = ts_nr_packets;
size = lines * llength;
if (0 != buf->vb.baddr && buf->vb.bsize < size)
@@ -135,7 +137,7 @@ static int buffer_prepare(struct file *f
static int
buffer_setup(struct file *file, unsigned int *count, unsigned int *size)
{
- *size = TS_PACKET_SIZE * TS_NR_PACKETS;
+ *size = TS_PACKET_SIZE * ts_nr_packets;
if (0 == *count)
*count = tsbufs;
*count = saa7134_buffer_count(*size,*count);
@@ -353,7 +355,7 @@ static int ts_do_ioctl(struct inode *ino
f->fmt.pix.width = 720; /* D1 */
f->fmt.pix.height = 576;
f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
- f->fmt.pix.sizeimage = TS_PACKET_SIZE*TS_NR_PACKETS;
+ f->fmt.pix.sizeimage = TS_PACKET_SIZE*ts_nr_packets;
return 0;
}
@@ -379,7 +381,7 @@ static int ts_do_ioctl(struct inode *ino
f->fmt.pix.width = 720; /* D1 */
f->fmt.pix.height = 576;
f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
- f->fmt.pix.sizeimage = TS_PACKET_SIZE*TS_NR_PACKETS;
+ f->fmt.pix.sizeimage = TS_PACKET_SIZE*ts_nr_packets;
return 0;
}
@@ -472,9 +474,9 @@ int saa7134_ts_init1(struct saa7134_dev
saa_writeb(SAA7134_TS_SERIAL1, 0x00); /* deactivate TS softreset */
saa_writeb(SAA7134_TS_PARALLEL, 0xec); /* TSSOP high active, TSVAL high active, TSLOCK ignored */
saa_writeb(SAA7134_TS_PARALLEL_SERIAL, (TS_PACKET_SIZE-1));
- saa_writeb(SAA7134_TS_DMA0, ((TS_NR_PACKETS-1)&0xff));
- saa_writeb(SAA7134_TS_DMA1, (((TS_NR_PACKETS-1)>>8)&0xff));
- saa_writeb(SAA7134_TS_DMA2, ((((TS_NR_PACKETS-1)>>16)&0x3f) | 0x00)); /* TSNOPIT=0, TSCOLAP=0 */
+ saa_writeb(SAA7134_TS_DMA0, ((ts_nr_packets-1)&0xff));
+ saa_writeb(SAA7134_TS_DMA1, (((ts_nr_packets-1)>>8)&0xff));
+ saa_writeb(SAA7134_TS_DMA2, ((((ts_nr_packets-1)>>16)&0x3f) | 0x00)); /* TSNOPIT=0, TSCOLAP=0 */
return 0;
}
Home |
Main Index |
Thread Index