/*******************************************************************

            MPEG file I/O interface (very very very slow)

 *******************************************************************/

#define MPEG_IO_C
#include "mpeg_io.h"

int open_mpeg_file(char *path, MPEG_IO *out);
int close_mpeg_file(MPEG_IO *p);
int get_bits(MPEG_IO *in, int num_of_bits);
int read_bits(MPEG_IO *in, int num_of_bits);
int erase_bits(MPEG_IO *in, int num_of_bits);
int next_marker(MPEG_IO *in);

static int fill_buffer(MPEG_IO *p);

/*******************************************************************/
int open_mpeg_file(char *path, MPEG_IO *out)
{
	strcpy(out->path, path);

	out->stream = fopen(path, "rb");
	if(out->stream == NULL){
		return 0;
	}

	out->buffer = 0;
	out->rest = 0;

	fill_buffer(out);

	return 1;
}
/*******************************************************************/
int close_mpeg_file(MPEG_IO *p)
{
	fclose(p->stream);
	return 1;
}
/*******************************************************************/
int get_bits(MPEG_IO *in, int num_of_bits)
{
	int r,n;

	if(num_of_bits > in->rest){
		n = num_of_bits - in->rest;
		r = in->buffer << n;
		
		in->rest = 0;
		in->buffer = 0;
		fill_buffer(in);

		r |= get_bits(in, n);
	}else{
		n = in->rest - num_of_bits;
		r = in->buffer >> n;
		in->buffer &= (1<<n)-1;
		in->rest = n;
		fill_buffer(in);
	}

	return r;
}
/*******************************************************************/
int read_bits(MPEG_IO *in, int num_of_bits)
{

	if(!fill_buffer(in)){
		return 0;
	}
	
	if(num_of_bits > in->rest){
		return 0;
	}

	return in->buffer >> (in->rest - num_of_bits);
}
/*******************************************************************/
int erase_bits(MPEG_IO *in, int num_of_bits)
{
	int n;

	if(!num_of_bits){
		return 1;
	}

	n = in->rest - num_of_bits;
	if(n < 0){
		return 0;
	}

	in->buffer &= (1<<n)-1;
	in->rest = n;

	return fill_buffer(in);
}
/*******************************************************************/
int next_marker(MPEG_IO *in)
{
	int code;
	
	erase_bits(in, in->rest%8);

	while( (code = read_bits(in, 24)) != 1){
		if(!erase_bits(in, 8)){
			return 0;
		}
	}

	return 1;
}
/*-----------------------------------------------------------------*/
static int fill_buffer(MPEG_IO *p)
{
	int i,n,c;

	n = sizeof(int)*8 - p->rest;
	n /= 8;
	
	for(i=0;i<n;i++){
		c = fgetc(p->stream);
		if(c == EOF){
			return 0;
		}
		p->buffer <<= 8;
		p->buffer |= c;
		p->rest += 8;
	}

	return 1;
}