#include <../source/TAL/objbase.h>

/* max 256 audio & video streams */
#define	MMSTREAM_AUDIO			0
#define	MMSTREAM_VIDEO			256

/*
 * Multimedia input
 */
vhandle_t	V_GLOBAL mmDemultiplex(vhandle_t filestream);
vhandle_t	V_GLOBAL mmSubstream(vhandle_t mmstream,u32_t substream_id);

/*
 * Multimedia output
 */
vboolean	V_GLOBAL mmMultiplex(vhandle_t output,char *format,char *acodec,char *vcodec);

#if 0
	The objective:
	
	=============== audio decoding =================
	vhandle_t in = fileOpenRead("test.wav");
	vhandle_t mms = mmDemultiplexWAV(in); /* in->addref */
	fileClose(in); /* in->release() on success; 'in' will be closed later */
	if(mms==LIBV_INVALID_HANDLE) /* no memory leak: 'in' was closed */
		return; /* corrupted audio file */
	vhandle_t audio = mmSubstream(mms,MMSTREAM_AUDIO); /* mms->addref */
	fileClose(mms); /* mms->release; 'mms' will be closed later */
	if(audio==LIBV_INVALID_HANDLE) /* no memory leak: 'mms' closed */
		return; /* audio stream is missing ? */
	...
	fileControl(audio,pctl_wave_get_num_channels,&nc);
	fileControl(audio,pctl_wave_get_bits_per_sample,&bps);
	fileControl(audio,pctl_wave_get_sampling_frequency,&sf);
	fragsize = nc * (bps >> 3) * sf;
	fileRead(audio,outbuf,fragsize); /* read in 1 second of audio */
	...
	fileClose(audio);
	/* --audio->ref_count==0; --mms->ref_count==0; --in->ref_count==0; all destroyed */
	
	=============== video decoding =================
	/* same as above, but for MMSTREAM_VIDEO (add n for (n+1)-th video track ) */
	...
	fileControl(video,pctl_video_get_width,&fw);
	fileControl(video,pctl_video_get_height,&fh);
	fileControl(video,pctl_video_get_fps,&fps);
	fileControl(video,pctl_video_num_frames,&nf);
	texdim = NOT_LESS_POWER_TWO((fw > fh) ? fw : fh);
	max_s = (vec_t)fw / (vec_t)texdim;
	max_t = (vec_t)fh / (vec_t)texdim;
	tmpbuf = memAlloc(texdim * texdim * 4);
	memZero(tmpbuf,texdim * texdim * 4);
	GLuint frametex;
	glGenTextures(1,&frametex);
	glBindTexture(frametex);
	...
	glTexSubImage2D(GL_TEXTURE_2D,0,4,texdim,texdim,0,GL_RGBA,GL_UNSIGNED_BYTE,tmpbuf);
	...
	fragsize = 4 * fw * fh;
	delay = 1000 / fps;

	for(i=0;i<nf;i++)
	{
		t = timeTickCount();
		/* Read next frame */
		fileRead(video,outbuf,fragsize); /* read in 1 frame */
		/* Blit it into square area */
		dptr = tmpbuf;
		sptr = oubuf;
		for(scan=0,scan<fh;scan++,sptr += fw*4,dptr += texdim*4)
			memCopy32(dptr,sptr,fw);

		/* Or, maybe:
		struct framestore_info fsi;
		fsi.width = texdim;
		fsi.height = texdim;
		fsi.xoffset = fsi.yoffset = 0;
		fsi.data = tmpbuf;
		fileControl(video,pctl_video_read_frame,&fsi);
		*/
		
		/* Download portion of texture to GPU */
		glTexSubImage2D(GL_TEXTURE_2D,0,0,0,fw,fh,GL_RGBA,GL_UNSIGNED_BYTE,tmpbuf);
		...
		/* render quad primitive */
			glTexCoord2d(0,0);
			...
			glTexCoord2d(max_s,0);
			...
			glTexCoord2d(max_s,max_t);
			...
			glTexCoord2d(0,max_t);
			...
		...
		vglSwapBuffers();
		...
		t = timeTickCount() - t;
		if(t<delay)
			timeDelay(delay - t);
	}
	...
	glBindTexture(0);
	glDeleteTextures(1,&frametex);
	memFree(tmpbuf);
	...
	fileClose(video); /* all streams destroyed, all handles closed */
	
#endif

typedef struct mmsubstream_s
{
	ioport_base_t	port;
	mmstreamid_t	id;
	vhandle_t		stream;
}	mmsubstream_t, *mmsubstream_p;

typedef struct mmstreams_s
{
	libv_object_t	base;
	vhandle_t		container;
	bstack_t		substreams;
}	mmstreams_t, *mmstreams_p;
