#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;
}

