Hello Mike,

With regards to our conversation about retrieving the YUV/PCM
information from the PVRUSB2, I've discovered some additional
information that I suspect you will find useful. It is as follows:

To reiterate, the commands to pull the information is as follows. They
can be sent one at a time, for audio/video only, or one immediately
after another for both.
// Start sending PCM (instead of sending 0x14 for MPEG)
pvr2_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2,0x01,0x12);

// Start sending YUV
pvr2_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2,0x01,0x11);


The stream consists of audio and video frames, in no particular
order. The audio "frames" are 0x1200 bytes in length (not including the
header), the video frames are 0x7E900 in length, and every video frame
is followed by some miscellaneous information of 0x120C in length
(Something to do with VBI, maybe?). Though, changes in the video
resolution or audio bitrate are likely to change those values.

To describe better than I can do in words, I've attached some code for
demuxing the streams. It's ugly, but it works. With it, I've been able
to play the captured audio and video, albeit with some caveats,
described below.
Note: It sometimes fails to find the audio header, which makes it not
possible to demux the stream. I intended to fix this, but it's getting
down to the last minute, and I'm quite sure you're capable of figuring
it out. The point is really only to convey the format of the stream.
Usage:
cat /dev/video0 > captured (CTRL-C, eventually)
pvr_demux captured audio_out.raw video_out.yuv

PCM Format:
The data is RAW PCM. It appears to be 16-bit, big-endian, but I'm not
certain of the frequency. It could possibly be controlled using the same
methods as for the MPEG data. Not knowing, or as of yet being able to
guess the frequency, the audio is clearly there, but it is distorted
(high/low pitched, too fast/slow).

YUV format:
The extracted stream can be played in mplayer using the following
command:
mplayer -rawvideo w=720:h=480:format=hm12 -demuxer rawvideo video.yuv

However, if I use format=hm12, the picture is fuzzy, but not distorted,
and the colours are wrong. If I use format=iyuv, the colours are
correct, but the picture is distorted. I'm guessing that the colourspace
conversion of which you spoke used by the ivtv guys would correct this.


I hope that is of some assistance. I'd be glad to help out with testing,
or anything else that may be necessary.

Thanks,
Graham
#include <stdio.h>
#include <errno.h>

#define MISC_DATA_LENGTH 0x120C	// VBI data? Exists at the end of every frame.
#define VIDEO_LENGTH 0x7E900	
#define AUDIO_LENGTH 0x1200	// This appears to always be the case, but also appears to be provided, so I'll use the provided information.

FILE *video, *audio, *source;

struct audio_header {
	unsigned int zero;	// Always zero.
	unsigned short count;	// Counts upwards. Coinciding with the 4 MSB of bf[0]
	unsigned char bf[4];	/* 
				 * Byte	Info
				 *
				 * 1	
				 *	Most Significant Nibble:	Counts upwards, usually by two, but by one and three occurs. The last four bytes of the above counter.
				 * 2    Most Significant Nibble: 	Unknown.
				 *	Least Significant Nibble: Counts downwards (every 5,6 or 7 packets)
				 * 3,4	Always zero. It seems.
				 */
				 
	unsigned short int audio_bytes;	// 0x0012. Interpreted as 0x1200, which may be a coincidence.
};

void parse_file() {
	struct audio_header header;
	unsigned char	*audio_bytes = (char*) &header.audio_bytes,
		audio_buff[AUDIO_LENGTH],
		video_buff[VIDEO_LENGTH],
		temp, found = 0;

	// Disregard the MPEG header. (Placed by device, or driver?)
	fseek(source, 2, SEEK_SET);
		
	while (fread(&header, sizeof(struct audio_header), 1, source) != 0) {
		temp = audio_bytes[0];
		audio_bytes[0] = audio_bytes[1];
		audio_bytes[1] = temp;

		// There's a varying number of "junk" (not understood by me) bytes at the beginning of the file. Usually 5-9, or somewhere along those lines.	
		// However, sometimes it seems the device starts sending in the middle of a video frame. Possibly the beginning. Unsure.
		if (!found && (header.zero != 0 || header.audio_bytes != 0x1200))
			fseek(source, -1 * ((sizeof(struct audio_header) - 1)), SEEK_CUR);
		else {
			found = !0;
			if (header.zero == 0) {	// Audio frame found.
				printf(" Audio Header (0x%08X)   ", ftell(source) - sizeof(struct audio_header));
				printf("0x%04X 0x%02X 0x%02X 0x%02X 0x%02X ", header.count, 
									      header.bf[0], header.bf[1], 
									      header.bf[2], header.bf[3]); 
	
				printf("(0x%x) \n", header.audio_bytes);
	
				fread(audio_buff, header.audio_bytes, 1, source);
				fwrite(audio_buff, header.audio_bytes, 1, audio);

			} else {	// Not audio. Must be video.
				fseek(source, sizeof(struct audio_header) * -1, SEEK_CUR);

				fread(video_buff, VIDEO_LENGTH, 1, source);
				fwrite(video_buff, VIDEO_LENGTH, 1, video);
					// Ignore the unknown data.
				fseek(source, MISC_DATA_LENGTH, SEEK_CUR);
			}
		}
	}
}

int main(int argc, char **argv) {
	if (argc != 4) {
		fprintf(stderr, "Usage %s input audio_file video_file\n", argv[0]);
		return -1;
	}

	source = fopen(argv[1], "r");
	audio = fopen(argv[2], "w");
	video = fopen(argv[3], "w");

	if (!audio || !video || !source) {
		perror("Couldn't open specified file");
		return -1;
	}

	parse_file();

	return 0;
}
_______________________________________________
pvrusb2 mailing list
[email protected]
http://www.isely.net/cgi-bin/mailman/listinfo/pvrusb2

Reply via email to