#include <stdio.h>
#include <string.h>
#include "OpenDMLParser.h"
#include "avi.h"

#define TRACE_THIS 1
#if TRACE_THIS
  #define TRACE printf
#else
  #define TRACE(a...)
#endif

struct movie_chunk
{
	movie_chunk *	next;
	int64			start;
	uint32			size;
};

OpenDMLParser::OpenDMLParser()
 :	fSource(0),
 	fSize(0),
 	fMovieListStart(0),
 	fStandardIndexStart(0),
 	fStandardIndexSize(0),
 	fStreamCount(0),
 	fMovieChunkCount(0),
	fAviMainHeaderValid(false),
	fOdmlExtendedHeaderValid(false),
	fStreams(0),
	fCurrentStream(0)
{
}

OpenDMLParser::~OpenDMLParser()
{
	// XXX free memory here!
}

int
OpenDMLParser::StreamCount()
{
	return fStreamCount;
}

const stream_info *
OpenDMLParser::StreamInfo(int index)
{
	if (index < 0 || index >= fStreamCount)
		return 0;
	
	stream_info *info = fStreams;
	while (index--)
		info = info->next;
	return info;
}

int64
OpenDMLParser::StandardIndexStart()
{
	return fStandardIndexStart;
}

uint32
OpenDMLParser::StandardIndexSize()
{
	return fStandardIndexSize;
}

int64
OpenDMLParser::MovieListStart()
{
	return fMovieListStart;
}

const avi_main_header *
OpenDMLParser::AviMainHeader()
{
	return fAviMainHeaderValid ? &fAviMainHeader : 0;
}

const odml_extended_header *
OpenDMLParser::OdmlExtendedHeader()
{
	return fOdmlExtendedHeaderValid ? &fOdmlExtendedHeader : 0;
}

void
OpenDMLParser::CreateNewStreamInfo()
{
	stream_info *info = new stream_info;
	info->next = 0;
	info->is_audio = false;
	info->is_video = false;
	info->stream_header_valid = false;
	info->audio_format = 0;
	info->video_format_valid = false;
	info->odml_index_start = 0;
	info->odml_index_size = 0;
	
	// append the new stream_info to the fStreams list and point fCurrentStream to it
	if (fStreams) {
		stream_info *cur = fStreams;
		while (cur->next)
			cur = cur->next;
		cur->next = info;
	} else {
		fStreams = info;
	}
	fCurrentStream = info;
}

void
OpenDMLParser::Parse(BPositionIO *source)
{
	TRACE("OpenDMLParser::Parse\n");
	
	fSource = source;
	fSize = source->Seek(0, SEEK_END);
	
	if (fSize < 32) {
		TRACE("OpenDMLParser::Parse: file to small\n");
		return;
	}
		
	uint64 pos = 0;
	int riff_chunk_number = 0;
	while (pos < (uint64)fSize) {
		uint32 temp;
		uint32 fourcc;
		uint32 size;

		if (sizeof(temp) != fSource->ReadAt(pos, &temp, sizeof(temp))) {
			TRACE("OpenDMLParser::Parse: read error at pos %llu\n", pos);
			goto err;
		}
		pos += 4;
		fourcc = AVI_UINT32(temp);

		if (sizeof(temp) != fSource->ReadAt(pos, &temp, sizeof(temp))) {
			TRACE("OpenDMLParser::Parse: read error at pos %llu\n", pos);
			goto err;
		}
		pos += 4;
		size = AVI_UINT32(temp);
		
		if (fourcc == FOURCC('J','U','N','K')) {
			TRACE("OpenDMLParser::Parse: JUNK chunk ignored, size: %lu bytes\n", size);
			goto cont;
		}

		if (fourcc != FOURCC('R','I','F','F')) {
			if (riff_chunk_number == 0) {
				TRACE("OpenDMLParser::Parse: not a RIFF file\n");
			} else {
				TRACE("OpenDMLParser::Parse: unknown chunk '"FOURCC_FORMAT"' (expected 'RIFF'), size = %lu  ignored\n", FOURCC_PARAM(fourcc), size);
				goto cont;
			}
		}

		TRACE("OpenDMLParser::Parse: RIFF chunk %d size: %lu bytes\n", riff_chunk_number, size);

		if (sizeof(temp) != fSource->ReadAt(pos, &temp, sizeof(temp))) {
			TRACE("OpenDMLParser::Parse: read error at pos %llu\n", pos);
			goto err;
		}
		fourcc = AVI_UINT32(temp);

		if (riff_chunk_number == 0 && fourcc != FOURCC('A','V','I',' ')) {
			TRACE("OpenDMLParser::Parse: not a AVI file\n");
			goto err;
		}

		if (fourcc != FOURCC('A','V','I',' ') && fourcc != FOURCC('A','V','I','X')) {
			TRACE("OpenDMLParser::Parse: unknown chunk '"FOURCC_FORMAT"' , size = %lu  ignored\n", FOURCC_PARAM(fourcc), size);
			goto cont;
		}
		
		ParseChunk_AVI(riff_chunk_number, pos + 4, size - 4);

cont:
		pos += (size) + (size & 1);
		riff_chunk_number++;
	}
	return;
	
err:
 	fStreamCount = 0;
}

void
OpenDMLParser::ParseChunk_AVI(int number, uint64 start, uint32 size)
{
	TRACE("OpenDMLParser::ParseChunk_AVI\n");
	uint64 pos = start;
	uint64 end = start + size;
	
	while (pos < end) {
		uint32 temp;
		uint32 Chunkfcc;
		uint32 Chunksize;

		if (sizeof(temp) != fSource->ReadAt(pos, &temp, sizeof(temp))) {
			TRACE("OpenDMLParser::ParseChunk_AVI: read error at pos %llu\n",pos);
			return;
		}
		pos += 4;
		Chunkfcc = AVI_UINT32(temp);
		
		if (sizeof(temp) != fSource->ReadAt(pos, &temp, sizeof(temp))) {
			TRACE("OpenDMLParser::ParseChunk_AVI: read error at pos %llu\n",pos);
			return;
		}
		pos += 4;
		Chunksize = AVI_UINT32(temp);

		TRACE("OpenDMLParser::ParseChunk_AVI: chunk '"FOURCC_FORMAT"', size = %lu\n", FOURCC_PARAM(Chunkfcc), Chunksize);

		if (Chunkfcc == FOURCC('J','U','N','K'))
			goto cont;
		else if (Chunkfcc == FOURCC('L','I','S','T'))
			ParseChunk_LIST(pos, Chunksize);
		else if (Chunkfcc == FOURCC('i','d','x','1')) {
			ParseChunk_idx1(pos, Chunksize);
		} else {
			TRACE("OpenDMLParser::ParseChunk_AVI: unknown chunk ignored\n");
		}

cont:
		pos += (Chunksize) + (Chunksize & 1);
	}
}

void
OpenDMLParser::ParseChunk_LIST(uint64 start, uint32 size)
{
	TRACE("OpenDMLParser::ParseChunk_LIST\n");
	uint32 temp;
	uint32 fourcc;

	if (sizeof(temp) != fSource->ReadAt(start, &temp, sizeof(temp))) {
		TRACE("OpenDMLParser::ParseChunk_LIST: read error at pos %llu\n", start);
		return;
	}
	fourcc = AVI_UINT32(temp);

	TRACE("OpenDMLParser::ParseChunk_LIST: type '"FOURCC_FORMAT"'\n", FOURCC_PARAM(fourcc));
	
	if (fourcc == FOURCC('m','o','v','i'))
		ParseList_movi(start + 4, size - 4);
	else if (fourcc == FOURCC('r','e','c',' '))
		ParseList_movi(start + 4, size - 4); //XXX parse rec simliar to movi???
	else if (fourcc == FOURCC('h','d','r','l'))
		ParseList_generic(start + 4, size - 4);
	else if (fourcc == FOURCC('s','t','r','l'))
		ParseList_strl(start + 4, size - 4);
	else if (fourcc == FOURCC('o','d','m','l'))
		ParseList_generic(start + 4, size - 4);
	else
		TRACE("OpenDMLParser::ParseChunk_LIST: unknown list type ignored\n");
}

void
OpenDMLParser::ParseChunk_idx1(uint64 start, uint32 size)
{
	TRACE("OpenDMLParser::ParseChunk_idx1\n");
	
	if (fStandardIndexSize != 0) {
		TRACE("OpenDMLParser::ParseChunk_idx1: found a second chunk\n");
		return;
	}

	fStandardIndexStart = start;
	fStandardIndexSize = size;
}

void
OpenDMLParser::ParseChunk_avih(uint64 start, uint32 size)
{
	TRACE("OpenDMLParser::ParseChunk_avih\n");

	if (fAviMainHeaderValid) {
		TRACE("OpenDMLParser::ParseChunk_avih: found a second chunk\n");
		return;
	}

	if (size < sizeof(fAviMainHeader)) {
		TRACE("OpenDMLParser::ParseChunk_avih: warning, avi header chunk too small\n");
	}

	memset(&fAviMainHeader, 0, sizeof(fAviMainHeader));
	size = min_c(size, sizeof(fAviMainHeader));
	if ((ssize_t)size != fSource->ReadAt(start, &fAviMainHeader, size)) {
		TRACE("OpenDMLParser::ParseChunk_avih: read error at pos %llu\n", start);
		return;
	}
	
	#if B_HOST_IS_BENDIAN
		B_SWAP_INT32(&fAviMainHeader.micro_sec_per_frame);
		B_SWAP_INT32(&fAviMainHeader.max_bytes_per_sec);
		B_SWAP_INT32(&fAviMainHeader.padding_granularity);
		B_SWAP_INT32(&fAviMainHeader.flags);
		B_SWAP_INT32(&fAviMainHeader.total_frames);
		B_SWAP_INT32(&fAviMainHeader.initial_frames);
		B_SWAP_INT32(&fAviMainHeader.streams);
		B_SWAP_INT32(&fAviMainHeader.suggested_buffer_size);
		B_SWAP_INT32(&fAviMainHeader.width);
		B_SWAP_INT32(&fAviMainHeader.height);
	#endif

	fAviMainHeaderValid = true;
	
	TRACE("fAviMainHeader:\n");
	TRACE("micro_sec_per_frame   = %lu\n", fAviMainHeader.micro_sec_per_frame);
	TRACE("max_bytes_per_sec     = %lu\n", fAviMainHeader.max_bytes_per_sec);
	TRACE("padding_granularity   = %lu\n", fAviMainHeader.padding_granularity);
	TRACE("flags                 = 0x%lx\n", fAviMainHeader.flags);
	TRACE("total_frames          = %lu\n", fAviMainHeader.total_frames);
	TRACE("initial_frames        = %lu\n", fAviMainHeader.initial_frames);
	TRACE("streams               = %lu\n", fAviMainHeader.streams);
	TRACE("suggested_buffer_size = %lu\n", fAviMainHeader.suggested_buffer_size);
	TRACE("width                 = %lu\n", fAviMainHeader.width);
	TRACE("height                = %lu\n", fAviMainHeader.height);
}

void
OpenDMLParser::ParseChunk_strh(uint64 start, uint32 size)
{
	TRACE("OpenDMLParser::ParseChunk_strh\n");
	
	if (fCurrentStream == 0) {
		TRACE("OpenDMLParser::ParseChunk_strh: error, no Stream info\n");
		return;
	}

	if (fCurrentStream->stream_header_valid) {
		TRACE("OpenDMLParser::ParseChunk_strh: error, already have stream header\n");
		return;
	}

	if (size < sizeof(fCurrentStream->stream_header)) {
		TRACE("OpenDMLParser::ParseChunk_strh: warning, avi stream header chunk too small\n");
	}

	memset(&fCurrentStream->stream_header, 0, sizeof(fCurrentStream->stream_header));

	size = min_c(size, sizeof(fCurrentStream->stream_header));
	if ((ssize_t)size != fSource->ReadAt(start, &fCurrentStream->stream_header, size)) {
		TRACE("OpenDMLParser::ParseChunk_strh: read error at pos %llu\n", start);
		return;
	}

	#if B_HOST_IS_BENDIAN
		B_SWAP_INT32(&fCurrentStream->stream_header.fourcc_type);
		B_SWAP_INT32(&fCurrentStream->stream_header.fourcc_handler);
		B_SWAP_INT32(&fCurrentStream->stream_header.flags);
		B_SWAP_INT16(&fCurrentStream->stream_header.priority);
		B_SWAP_INT16(&fCurrentStream->stream_header.language);
		B_SWAP_INT32(&fCurrentStream->stream_header.initial_frames);
		B_SWAP_INT32(&fCurrentStream->stream_header.scale);
		B_SWAP_INT32(&fCurrentStream->stream_header.rate);
		B_SWAP_INT32(&fCurrentStream->stream_header.start);
		B_SWAP_INT32(&fCurrentStream->stream_header.length);
		B_SWAP_INT32(&fCurrentStream->stream_header.suggested_buffer_size);
		B_SWAP_INT32(&fCurrentStream->stream_header.quality);
		B_SWAP_INT32(&fCurrentStream->stream_header.sample_size);
		B_SWAP_INT16(&fCurrentStream->stream_header.rect_left);
		B_SWAP_INT16(&fCurrentStream->stream_header.rect_top);
		B_SWAP_INT16(&fCurrentStream->stream_header.rect_right);
		B_SWAP_INT16(&fCurrentStream->stream_header.rect_bottom);
	#endif

	fCurrentStream->stream_header_valid = true;
	fCurrentStream->is_audio = fCurrentStream->stream_header.fourcc_type == FOURCC('a','u','d','s');
	fCurrentStream->is_video = fCurrentStream->stream_header.fourcc_type == FOURCC('v','i','d','s');

	TRACE("stream_header, Stream %d, is_audio %d, is_video %d:\n", fStreamCount - 1, fCurrentStream->is_audio, fCurrentStream->is_video);
	TRACE("fourcc_type           = '"FOURCC_FORMAT"'\n",FOURCC_PARAM(fCurrentStream->stream_header.fourcc_type));
	TRACE("fourcc_handler        = '"FOURCC_FORMAT"'\n",FOURCC_PARAM(fCurrentStream->stream_header.fourcc_handler));
	TRACE("flags                 = 0x%lx\n", fCurrentStream->stream_header.flags);
	TRACE("priority              = %u\n", fCurrentStream->stream_header.priority);
	TRACE("language              = %u\n", fCurrentStream->stream_header.language);
	TRACE("initial_frames        = %lu\n", fCurrentStream->stream_header.initial_frames);
	TRACE("scale                 = %lu\n", fCurrentStream->stream_header.scale);
	TRACE("rate                  = %lu\n", fCurrentStream->stream_header.rate);
	TRACE("frames/sec            = %.3f\n", fCurrentStream->stream_header.rate / (float)fCurrentStream->stream_header.scale);
	TRACE("start                 = %lu\n", fCurrentStream->stream_header.start);
	TRACE("length                = %lu\n", fCurrentStream->stream_header.length);
	TRACE("suggested_buffer_size = %lu\n", fCurrentStream->stream_header.suggested_buffer_size);
	TRACE("quality               = %lu\n", fCurrentStream->stream_header.quality);
	TRACE("sample_size           = %lu\n", fCurrentStream->stream_header.sample_size);
	TRACE("rect_left             = %d\n", fCurrentStream->stream_header.rect_left);
	TRACE("rect_top              = %d\n", fCurrentStream->stream_header.rect_top);
	TRACE("rect_right            = %d\n", fCurrentStream->stream_header.rect_right );
	TRACE("rect_bottom           = %d\n", fCurrentStream->stream_header.rect_bottom);
}

void
OpenDMLParser::ParseChunk_strf(uint64 start, uint32 size)
{
	TRACE("OpenDMLParser::ParseChunk_strf, size %lu\n", size);

	if (fCurrentStream == 0) {
		TRACE("OpenDMLParser::ParseChunk_strf: error, no Stream info\n");
		return;
	}
	
	if (fCurrentStream->is_audio) {

		if (fCurrentStream->audio_format) {
			TRACE("OpenDMLParser::ParseChunk_strf: error, already have audio format header\n");
			return;
		}

//		if (size < sizeof(fCurrentStream->audio_format)) {
//			TRACE("OpenDMLParser::ParseChunk_strf: warning, avi audio header chunk too small\n");
//		}

		// if size to read is less then	sizeof(wave_format_ex), allocate
		// a full wave_format_ex and fill reminder with zero bytes
		fCurrentStream->audio_format_size = max_c(sizeof(wave_format_ex), size);
		fCurrentStream->audio_format = (wave_format_ex *) new char[fCurrentStream->audio_format_size];
		memset(size + (char *)fCurrentStream->audio_format, 0, fCurrentStream->audio_format_size - size);

		if ((ssize_t)size != fSource->ReadAt(start, fCurrentStream->audio_format, size)) {
			TRACE("OpenDMLParser::ParseChunk_strf: read error at pos %llu\n", start);
			delete [] fCurrentStream->audio_format;
			fCurrentStream->audio_format_size = 0;
			fCurrentStream->audio_format = 0;
			return;
		}
		
		#if B_HOST_IS_BENDIAN
			B_SWAP_INT16(&fCurrentStream->audio_format->format_tag);
			B_SWAP_INT16(&fCurrentStream->audio_format->channels);
			B_SWAP_INT32(&fCurrentStream->audio_format->frames_per_sec);
			B_SWAP_INT32(&fCurrentStream->audio_format->avg_bytes_per_sec);
			B_SWAP_INT32(&fCurrentStream->audio_format->block_align);
			B_SWAP_INT32(&fCurrentStream->audio_format->bits_per_sample);
			B_SWAP_INT32(&fCurrentStream->audio_format->extra_size);
		#endif

		TRACE("audio_format:\n");
		TRACE("format_tag        = 0x%x\n", fCurrentStream->audio_format->format_tag);
		TRACE("channels          = %u\n", fCurrentStream->audio_format->channels);
		TRACE("frames_per_sec    = %lu\n", fCurrentStream->audio_format->frames_per_sec);
		TRACE("avg_bytes_per_sec = %lu\n", fCurrentStream->audio_format->avg_bytes_per_sec);
		TRACE("block_align       = %u\n", fCurrentStream->audio_format->block_align);
		TRACE("bits_per_sample   = %u\n", fCurrentStream->audio_format->bits_per_sample);
		TRACE("extra_size        = %u\n", fCurrentStream->audio_format->extra_size);
		
		// XXX read extra data
	
	} else if (fCurrentStream->is_video) {

		if (fCurrentStream->video_format_valid) {
			TRACE("OpenDMLParser::ParseChunk_strf: error, already have video format header\n");
			return;
		}
	
//		if (size < sizeof(fCurrentStream->video_format)) {
//			TRACE("OpenDMLParser::ParseChunk_strf: warning, avi video header chunk too small\n");
//		}
	
		memset(&fCurrentStream->video_format, 0, sizeof(fCurrentStream->video_format));
	
		size = min_c(size, sizeof(fCurrentStream->video_format));
		if ((ssize_t)size != fSource->ReadAt(start, &fCurrentStream->video_format, size)) {
			TRACE("OpenDMLParser::ParseChunk_strf: read error at pos %llu\n", start);
			return;
		}
		
		#if B_HOST_IS_BENDIAN
			B_SWAP_INT32(&fCurrentStream->video_format.size);
			B_SWAP_INT32(&fCurrentStream->video_format.width);
			B_SWAP_INT32(&fCurrentStream->video_format.height);
			B_SWAP_INT16(&fCurrentStream->video_format.planes);
			B_SWAP_INT16(&fCurrentStream->video_format.bit_count);
			B_SWAP_INT32(&fCurrentStream->video_format.compression);
			B_SWAP_INT32(&fCurrentStream->video_format.image_size);
			B_SWAP_INT32(&fCurrentStream->video_format.x_pels_per_meter);
			B_SWAP_INT32(&fCurrentStream->video_format.y_pels_per_meter);
			B_SWAP_INT32(&fCurrentStream->video_format.clr_used);
			B_SWAP_INT32(&fCurrentStream->video_format.clr_important);
		#endif

		fCurrentStream->video_format_valid = true;

		TRACE("video_format:\n");
		TRACE("size             = %lu\n", fCurrentStream->video_format.size);
		TRACE("width            = %lu\n", fCurrentStream->video_format.width);
		TRACE("height           = %lu\n", fCurrentStream->video_format.height);
		TRACE("planes           = %u\n", fCurrentStream->video_format.planes);
		TRACE("bit_count        = %u\n", fCurrentStream->video_format.bit_count);
		TRACE("compression      = 0x%08lx\n", fCurrentStream->video_format.compression);
		TRACE("image_size       = %lu\n", fCurrentStream->video_format.image_size);
		TRACE("x_pels_per_meter = %lu\n", fCurrentStream->video_format.x_pels_per_meter);
		TRACE("y_pels_per_meter = %lu\n", fCurrentStream->video_format.y_pels_per_meter);
		TRACE("clr_used         = %lu\n", fCurrentStream->video_format.clr_used);
		TRACE("clr_important    = %lu\n", fCurrentStream->video_format.clr_important);

	} else {
		TRACE("OpenDMLParser::ParseChunk_strf: error, unknown Stream type\n");
	}
}

void
OpenDMLParser::ParseChunk_indx(uint64 start, uint32 size)
{
	TRACE("OpenDMLParser::ParseChunk_indx\n");

	if (fCurrentStream == 0) {
		TRACE("OpenDMLParser::ParseChunk_indx: error, no stream info\n");
		return;
	}
	// XXX
	fCurrentStream->odml_index_start = start;
	fCurrentStream->odml_index_size = size;
}

void
OpenDMLParser::ParseChunk_dmlh(uint64 start, uint32 size)
{
	TRACE("OpenDMLParser::ParseChunk_dmlh\n");

	if (fOdmlExtendedHeaderValid) {
		TRACE("OpenDMLParser::ParseChunk_dmlh: found a second chunk\n");
		return;
	}

	if (size < sizeof(fOdmlExtendedHeader)) {
		TRACE("OpenDMLParser::ParseChunk_dmlh: warning, avi header chunk too small\n");
	}

	memset(&fOdmlExtendedHeader, 0, sizeof(fOdmlExtendedHeader));
	size = min_c(size, sizeof(fOdmlExtendedHeader));
	if ((ssize_t)size != fSource->ReadAt(start, &fOdmlExtendedHeader, size)) {
		TRACE("OpenDMLParser::ParseChunk_dmlh: read error at pos %llu\n", start);
		return;
	}
	
	#if B_HOST_IS_BENDIAN
		B_SWAP_INT32(&fOdmlExtendedHeader.total_frames);
	#endif

	fOdmlExtendedHeaderValid = true;
	
	TRACE("fOdmlExtendedHeader:\n");
	TRACE("total_frames   = %ld\n", fOdmlExtendedHeader.total_frames);
}

void
OpenDMLParser::ParseList_strl(uint64 start, uint32 size)
{
	TRACE("OpenDMLParser::ParseList_strl\n");

	CreateNewStreamInfo();
	fStreamCount++;

	ParseList_generic(start, size);
}

void
OpenDMLParser::ParseList_generic(uint64 start, uint32 size)
{
	TRACE("OpenDMLParser::ParseList_generic\n");
	uint64 pos = start;
	uint64 end = start + size;

	while (pos < end) {
		uint32 temp;
		uint32 Chunkfcc;
		uint32 Chunksize;

		if (sizeof(temp) != fSource->ReadAt(pos, &temp, sizeof(temp))) {
			TRACE("OpenDMLParser::ParseList_generic: read error at pos %llu\n",pos);
			return;
		}
		pos += 4;
		Chunkfcc = AVI_UINT32(temp);
		
		if (sizeof(temp) != fSource->ReadAt(pos, &temp, sizeof(temp))) {
			TRACE("OpenDMLParser::ParseList_generic: read error at pos %llu\n",pos);
			return;
		}
		pos += 4;
		Chunksize = AVI_UINT32(temp);

		TRACE("OpenDMLParser::ParseList_generic: chunk '"FOURCC_FORMAT"', size = %ld\n", FOURCC_PARAM(Chunkfcc), Chunksize);

		if (Chunkfcc == FOURCC('J','U','N','K'))
			goto cont;
		else if (Chunkfcc == FOURCC('a','v','i','h'))
			ParseChunk_avih(pos, Chunksize);
		else if (Chunkfcc == FOURCC('L','I','S','T'))
			ParseChunk_LIST(pos, Chunksize);
		else if (Chunkfcc == FOURCC('s','t','r','h'))
			ParseChunk_strh(pos, Chunksize);
		else if (Chunkfcc == FOURCC('s','t','r','f'))
			ParseChunk_strf(pos, Chunksize);
		else if (Chunkfcc == FOURCC('i','n','d','x'))
			ParseChunk_indx(pos, Chunksize);
		else if (Chunkfcc == FOURCC('d','m','l','h'))
			ParseChunk_dmlh(pos, Chunksize);
		else
			TRACE("OpenDMLParser::ParseList_generic: unknown chunk ignored\n");

cont:
		pos += (Chunksize) + (Chunksize & 1);
	}
}

void
OpenDMLParser::ParseList_movi(uint64 start, uint32 size)
{
	TRACE("OpenDMLParser::ParseList_movi\n");

	if (fMovieListStart == 0)
		fMovieListStart = start;
	
	fMovieChunkCount++;
	return;
}

