Drawing rgb565 image in output_buffer using PVR

If you have any questions on programming, this is the place to ask them, whether you're a newbie or an experienced programmer. Discussion on programming in general is also welcome. We will help you with programming homework, but we will not do your work for you! Any porting requests must be made in Developmental Ideas.
User avatar
PH3NOM
DC Developer
DC Developer
Posts: 576
https://www.artistsworkshop.eu/meble-kuchenne-na-wymiar-warszawa-gdzie-zamowic/
Joined: Fri Jun 18, 2010 9:29 pm
Has thanked: 0
Been thanked: 5 times

Drawing rgb565 image in output_buffer using PVR

Post by PH3NOM »

So, I am still trying to become familiar with the PVR hardware, and dreamcast programming in general.

I just cross-compiled libxvid.1.2.2 as a static lib for dc.
I have cross-compiled the test app xvid_decraw for DC, currently using rgb565 colorspace output.
Without optimizations, the dreamcast is able decode 320x240 video at ~2x playback speed. Not bad.

What I have is a rgb565 image, stored in memory, and I need to know how to display the image using the PVR hardware, using display mode PVR_TXRFMT_RGB565.

Any help appreciated!
User avatar
BB Hood
DC Developer
DC Developer
Posts: 189
Joined: Fri Mar 30, 2007 12:09 am
Has thanked: 41 times
Been thanked: 10 times

Re: Drawing rgb565 image in output_buffer using PVR

Post by BB Hood »

I'll try and help.

So the image is stored in memory and it is uncompressed correct?

If so, you could do something like this(pseudo code):

Code: Select all

uint16 Image_width, Image_height;
pvr_poly_hdr_t Image_Header; // The thing that is submitted to the PVR before drawing
pvr_poly_cxt_t Image_context; // Used to make header. Basically the context is readable to us while the header is readable to the PVR
pvr_dr_state_t state; // For direct rendering.  You will probably need this.
pvr_vertex_t *vert;  

....

// Allocate PVR Memory
pvr_ptr_t Image_data = pvr_mem_malloc(Image_width * Image_height * 2);    

// Load texture data from an SH-4 buffer into PVR RAM, twiddling it in the process
pvr_txr_load_ex((void *)rawimagedata, Image_data, Image_width, Image_height, PVR_TXRLOAD_16BPP); 

//rawimagedata is the image data you have stored in memory.

// Create a textured polygon context 
void pvr_poly_cxt_txr(&Image_context, PVR_LIST_OP_POLY, PVR_TXRFMT_RGB565 | PVR_TXRFMT_TWIDDLED, Image_width, Image_height, Image_data, PVR_FILTER_BILINEAR);
pvr_poly_compile(&Image_Header, &Image_context); // Convert the context into something the pvr can read
...
// drawing
	pvr_wait_ready();
	pvr_scene_begin();
	pvr_list_begin(PVR_LIST_OP_POLY);

        pvr_dr_init(state); // initialize the dr state variable
        pvr_prim(&Image_Header, sizeof(pvr_poly_hdr_t));  // Submit image header to PVR

        // bottom left
		vert = pvr_dr_target(state);
		vert->flags = PVR_CMD_VERTEX;
		vert->x = 0;
		vert->y = Image_height;
		vert->z = 2;
		vert->u = 0;
		vert->v = 1;
                vert->oargb = 0;
		vert->argb = 0xffffffff;
		pvr_dr_commit(vert);

		// top left
		vert = pvr_dr_target(state);
		vert->flags = PVR_CMD_VERTEX;
		vert->x = 0;
		vert->y = 0;
		vert->z = 2;
		vert->u = 0;
		vert->v = 0;
		vert->argb = 0xffffffff;
		pvr_dr_commit(vert);

		// bottom right
		vert = pvr_dr_target(state);
		vert->flags = PVR_CMD_VERTEX;
		vert->x = Image_width;
		vert->y = Image_height;
		vert->z = 2;
		vert->u = 1;
		vert->v = 1;
		vert->argb = 0xffffffff;
		pvr_dr_commit(vert);

		// top right
		vert = pvr_dr_target(state);
		vert->flags = PVR_CMD_VERTEX_EOL;
		vert->x = Image_width;
		vert->y = Image_height;
		vert->z = 2;
		vert->u = 1;
		vert->v = 0;
		vert->argb = 0xffffffff;
		pvr_dr_commit(vert);

pvr_scene_finish();

I took a glimpse at your other thread so I guess your going to be using the whole screen which is why I set the x and y vertexs like that. There are plenty of examples of PVR usage included with KOS.

Check out pvr.h in the "\usr\local\dc\kos\kos\kernel\arch\dreamcast\include\dc" directory for more help.
User avatar
PH3NOM
DC Developer
DC Developer
Posts: 576
Joined: Fri Jun 18, 2010 9:29 pm
Has thanked: 0
Been thanked: 5 times

Re: Drawing rgb565 image in output_buffer using PVR

Post by PH3NOM »

Thanks for the help, it is similar with other examples I was looking at.
Ive almost got it to work.

I think my problem is Im not sure exactly what parameter to pass here.

Code: Select all

//rawimagedata is the image data you have stored in memory.
Is it the name of the variable that represents the location in memory?

When I try to pass the parameter as "output_buffer" ( the location in memory where the decoded rgb565 frames are stored ) the image is not displayed right at all...take a look!

Image
User avatar
BB Hood
DC Developer
DC Developer
Posts: 189
Joined: Fri Mar 30, 2007 12:09 am
Has thanked: 41 times
Been thanked: 10 times

Re: Drawing rgb565 image in output_buffer using PVR

Post by BB Hood »

PH3NOM wrote:I think my problem is Im not sure exactly what parameter to pass here.

Code: Select all

//rawimagedata is the image data you have stored in memory.
Is it the name of the variable that represents the location in memory?
Yes, its a pointer to the raw data (decoded rgb565 frame). Make sure it is a pointer to one single decoded rgb565 frame just to be safe.
PH3NOM wrote: When I try to pass the parameter as "output_buffer" ( the location in memory where the decoded rgb565 frames are stored ) the image is not displayed right at all.
Thats my fault. The last vertex submit was incorrect. Replace with this:

Code: Select all

// top right
      vert = pvr_dr_target(state);
      vert->flags = PVR_CMD_VERTEX_EOL;
      vert->x = Image_width;
      vert->y = 0;
      vert->z = 2;
      vert->u = 1;
      vert->v = 0;
      vert->argb = 0xffffffff;
      pvr_dr_commit(vert);
I don't think that will fix the scrambled up image but if you could post some of your code, I and everyone else can take a look at it to see if we can help you further. I had the same problem(scrambled image) when I worked on DCMappy...I had a problem with endianness. Is the raw image data in big endian or little endian? Are you sure the decoded data is rgb565?
User avatar
PH3NOM
DC Developer
DC Developer
Posts: 576
Joined: Fri Jun 18, 2010 9:29 pm
Has thanked: 0
Been thanked: 5 times

Re: Drawing rgb565 image in output_buffer using PVR

Post by PH3NOM »

Yeah I set the vertexes correctly for a 640x480 screen, so that part is worked out.

Also, I tried big and little endian, resulting in different colors but still similar to the last screen I posted.

The images should be RGB 16bit, as I have this defined in the code:

Code: Select all

			CSP = XVID_CSP_RGB555;
				BPP = 2;
Here are the other colorspace profiles built in the decoder, I think RGB 16bit is the only one DC can accept?:

Code: Select all

			if (strcmp(argv[i], "rgb16") == 0) {
				CSP = XVID_CSP_RGB555;
				BPP = 2;
			} else if (strcmp(argv[i], "rgb24") == 0) {
				CSP = XVID_CSP_BGR;
				BPP = 3;
			} else if (strcmp(argv[i], "rgb32") == 0) {
				CSP = XVID_CSP_BGRA;
				BPP = 4;
			} else if (strcmp(argv[i], "yv12") == 0) {
				CSP = XVID_CSP_YV12;
				BPP = 1;
			} else {
				CSP = XVID_CSP_I420;
				BPP = 1;
And the buffer is set up like this:

Code: Select all

out_buffer = (unsigned char*)malloc(XDIM*YDIM*4);
User avatar
BlueCrab
The Crabby Overlord
The Crabby Overlord
Posts: 5652
Joined: Mon May 27, 2002 11:31 am
Location: Sailing the Skies of Arcadia
Has thanked: 9 times
Been thanked: 69 times
Contact:

Re: Drawing rgb565 image in output_buffer using PVR

Post by BlueCrab »

RGB555 and RGB565 are two different things. Also, I seriously doubt you're using a twiddled texture (as the example code that was posted assumed).

Take the line:

Code: Select all

pvr_poly_cxt_txr(&Image_context, PVR_LIST_OP_POLY, PVR_TXRFMT_RGB565 | PVR_TXRFMT_TWIDDLED, Image_width, Image_height, Image_data, PVR_FILTER_BILINEAR);
and change it to:

Code: Select all

pvr_poly_cxt_txr(&Image_context, PVR_LIST_OP_POLY, PVR_TXRFMT_ARGB1555 | PVR_TXRFMT_NONTWIDDLED, Image_width, Image_height, Image_data, PVR_FILTER_BILINEAR);
User avatar
BB Hood
DC Developer
DC Developer
Posts: 189
Joined: Fri Mar 30, 2007 12:09 am
Has thanked: 41 times
Been thanked: 10 times

Re: Drawing rgb565 image in output_buffer using PVR

Post by BB Hood »

BlueCrab wrote: I seriously doubt you're using a twiddled texture (as the example code that was posted assumed).
Wouldn't the pvr_txr_load_ex() function twiddle it for him?

Code: Select all

pvr_poly_cxt_txr(&Image_context, PVR_LIST_OP_POLY, PVR_TXRFMT_ARGB1555 | PVR_TXRFMT_NONTWIDDLED, Image_width, Image_height, Image_data, PVR_FILTER_BILINEAR);
If the above code doesn't work try:

Code: Select all

pvr_poly_cxt_txr(&Image_context, PVR_LIST_OP_POLY, PVR_TXRFMT_ARGB1555 | PVR_TXRFMT_TWIDDLED, Image_width, Image_height, Image_data, PVR_FILTER_BILINEAR);
User avatar
BlueCrab
The Crabby Overlord
The Crabby Overlord
Posts: 5652
Joined: Mon May 27, 2002 11:31 am
Location: Sailing the Skies of Arcadia
Has thanked: 9 times
Been thanked: 69 times
Contact:

Re: Drawing rgb565 image in output_buffer using PVR

Post by BlueCrab »

BB Hood wrote:
BlueCrab wrote: I seriously doubt you're using a twiddled texture (as the example code that was posted assumed).
Wouldn't the pvr_txr_load_ex() function twiddle it for him?

Code: Select all

pvr_poly_cxt_txr(&Image_context, PVR_LIST_OP_POLY, PVR_TXRFMT_ARGB1555 | PVR_TXRFMT_NONTWIDDLED, Image_width, Image_height, Image_data, PVR_FILTER_BILINEAR);
If the above code doesn't work try:

Code: Select all

pvr_poly_cxt_txr(&Image_context, PVR_LIST_OP_POLY, PVR_TXRFMT_ARGB1555 | PVR_TXRFMT_TWIDDLED, Image_width, Image_height, Image_data, PVR_FILTER_BILINEAR);
True, it would, but that image almost looks like the twiddling hasn't been applied (yet is assumed to be done by the hardware), to me anyway.

That said, PVR_TXRFMT_TWIDDLED is 0 (well, (0 << 26), which is still 0), so it makes no difference whether it's there or not (and since its a hardware flag, its not going to change from 0). Technically, PVR_TXRFMT_ARGB1555 is also zero... but you'd just confuse people if you had a 0 instead of something there. :wink:
User avatar
PH3NOM
DC Developer
DC Developer
Posts: 576
Joined: Fri Jun 18, 2010 9:29 pm
Has thanked: 0
Been thanked: 5 times

Re: Drawing rgb565 image in output_buffer using PVR

Post by PH3NOM »

Awesome News!
I have got the decoder drawing every decoded frame with the help here!

Image

And, BlueCrab, the rgb555 is misleading, it really is RGB565 as I thought, it is not ARGB1555.
My problem was setting the height and width incorrectly for the texture, I still need to learn more so this will work on arbitrary resolutions...

Here is what ended up working:

Code: Select all

/////////////////////////////////////////////////////////////
pvr_poly_hdr_t Image_Header; // The thing that is submitted to the PVR before drawing
pvr_poly_cxt_t Image_context; // Used to make header. Basically the context is readable to us while the header is readable to the PVR
pvr_dr_state_t state; // For direct rendering.  You will probably need this.
pvr_vertex_t *vert; 


// Allocate PVR Memory
pvr_ptr_t Image_data = pvr_mem_malloc(XDIM * YDIM * 2);   


// Load texture data from an SH-4 buffer into PVR RAM, twiddling it in the process
pvr_txr_load_ex((void *)out_buffer, Image_data, XDIM, YDIM, PVR_TXRLOAD_16BPP);
//out_buffer is the decoded frame stored in memory.

// Create a textured polygon context
pvr_poly_cxt_txr(&Image_context, PVR_LIST_OP_POLY, PVR_TXRFMT_RGB565 | PVR_TXRFMT_TWIDDLED, XDIM, YDIM, Image_data, PVR_FILTER_BILINEAR);
pvr_poly_compile(&Image_Header, &Image_context); // Convert the context into something the pvr can read

// drawing
   pvr_wait_ready();
   pvr_scene_begin();
   pvr_list_begin(PVR_LIST_OP_POLY);

        pvr_dr_init(state); // initialize the dr state variable
        pvr_prim(&Image_Header, sizeof(pvr_poly_hdr_t));  // Submit image header to PVR

        // bottom left
      vert = pvr_dr_target(state);
      vert->flags = PVR_CMD_VERTEX;
      vert->x = 1;
      vert->y = 376;
      vert->z = 2;
      vert->u = 0;
      vert->v = 1;
      //vert->oargb = 0;
      vert->argb = 0xffffffff;
      pvr_dr_commit(vert);

      // top left
      vert = pvr_dr_target(state);
      vert->flags = PVR_CMD_VERTEX;
      vert->x = 1;
      vert->y = 104;
      vert->z = 2;
      vert->u = 0;
      vert->v = 0;
      vert->argb = 0xffffffff;
      pvr_dr_commit(vert);

      // bottom right
      vert = pvr_dr_target(state);
      vert->flags = PVR_CMD_VERTEX;
      vert->x = 640;
      vert->y = 376;
      vert->z = 2;
      vert->u = 1;
      vert->v = 1;
      vert->argb = 0xffffffff;
      pvr_dr_commit(vert);

      // top right
      vert = pvr_dr_target(state);
      vert->flags = PVR_CMD_VERTEX_EOL;
      vert->x = 640;
      vert->y = 104;
      vert->z = 2;
      vert->u = 1;
      vert->v = 0;
      vert->argb = 0xffffffff;
      pvr_dr_commit(vert);

pvr_scene_finish();
pvr_mem_free(Image_data);
//pvr_mem_reset();
///////////////////////////////////////////////////////////
XDIM and YDIM are the width and height of the .m4v video, as determined by the decoder.
out_buffer contains the decoded RGB565 frames.
The code, as is, will decode a sample.m4v xvid video ( must be encoded at a pvr-compatible resolution? ) and display it centered at 640x272.
It will be easy from here to adjust the vertex pointers according to XDIM and YDIM.

But, what would it take to implement this via PVR DMA?
User avatar
BlueCrab
The Crabby Overlord
The Crabby Overlord
Posts: 5652
Joined: Mon May 27, 2002 11:31 am
Location: Sailing the Skies of Arcadia
Has thanked: 9 times
Been thanked: 69 times
Contact:

Re: Drawing rgb565 image in output_buffer using PVR

Post by BlueCrab »

Well, DMA itself isn't going to magically make your code run any faster. If you have things planned out enough such that you can have one frame done decoding while another is decoding, you could transfer the one that is done using non-blocking DMA. That would make the transfer effectively "free", and could help with speed, however it can be a bit of a pain dealing with things in that way.

If you're going to use DMA, there are various functions in the KOS pvr.h header that deal with it (the main one you'd probably want to use is pvr_txr_load_dma). Note that your texture will certainly NOT be twiddled if you do a DMA transfer of it to texture memory. Also, you may run into cache related issues as well (so you should probably flush the dcache (dcache_flush_range in kos/kernel/arch/dreamcast/include/arch/cache.h) over the area where you render your frame into before you try to load the texture to texture memory).
User avatar
PH3NOM
DC Developer
DC Developer
Posts: 576
Joined: Fri Jun 18, 2010 9:29 pm
Has thanked: 0
Been thanked: 5 times

Re: Drawing rgb565 image in output_buffer using PVR

Post by PH3NOM »

Small update:

XviD operates internally at YV12.
Using RGB565 colorspace was slow..

Turns out it is possible to use faster xvid internal colorspace conversion
to convert YV12 to UYVY that works with PVR_TXRFMT_YUV422...
User avatar
BB Hood
DC Developer
DC Developer
Posts: 189
Joined: Fri Mar 30, 2007 12:09 am
Has thanked: 41 times
Been thanked: 10 times

Re: Drawing rgb565 image in output_buffer using PVR

Post by BB Hood »

Probably should have told you that in the beginning: viewtopic.php?p=1009854#p1009854

Did you do any DMA stuff yet?
User avatar
PH3NOM
DC Developer
DC Developer
Posts: 576
Joined: Fri Jun 18, 2010 9:29 pm
Has thanked: 0
Been thanked: 5 times

Re: Drawing rgb565 image in output_buffer using PVR

Post by PH3NOM »

No not yet.
It looks like I will need to re-write a few things, and implement store-queues first to implement PVR DMA.

First I have a few other optimizations to make, like getting the video output function executing in its own thread, and get more speedups in the decoder.

I have made other optimizations, though:
-extracting the fast sh4_idct by Bero from ffmpeg and patched into libxvidcore
-removed some un-necessary decoder functions like post processing...
User avatar
BlueCrab
The Crabby Overlord
The Crabby Overlord
Posts: 5652
Joined: Mon May 27, 2002 11:31 am
Location: Sailing the Skies of Arcadia
Has thanked: 9 times
Been thanked: 69 times
Contact:

Re: Drawing rgb565 image in output_buffer using PVR

Post by BlueCrab »

pvr_txr_load always uses the store queues to copy data. pvr_txr_load_ex, on the other hand, does not (since its doing the twiddling). If you do not have to do twiddling, it will make things faster to just simply not do it. I doubt you're doing anything that would make using twiddled textures significantly better, so you might want to explore that.

That said, it is entirely possible to write a function to twiddle into the store queues and then use the store queues to do a burst transfer to video memory. I believe that Genesis Plus DC uses a trick like this (although, it uses palleted textures, I think -- the idea is still the same though).
User avatar
PH3NOM
DC Developer
DC Developer
Posts: 576
Joined: Fri Jun 18, 2010 9:29 pm
Has thanked: 0
Been thanked: 5 times

Re: Drawing rgb565 image in output_buffer using PVR

Post by PH3NOM »

Edit:

I have made a huge speed boost in the code! This code is about 2x faster now.

What I have done, is decoded the frames directly into PVR ram.
This skips needing to load the texture from SH4 buffer into PVR ram.
This also bypasses having to use "pvr_txr_load_ex" and twiddle the texture.

Code: Select all

					/* Free old output buffer*/
					//if(out_buffer) free(out_buffer);
                    if(out_buffer) pvr_mem_free(out_buffer);

					/* Allocate the new buffer */
					//out_buffer = (unsigned char*)malloc(XDIM*YDIM*4);
					out_buffer = (unsigned char*)pvr_mem_malloc(XDIM*YDIM*2);

Code: Select all

       // Allocate PVR Memory
       //pvr_ptr_t Image_data = pvr_mem_malloc(XDIM*YDIM*2);   
       
       // Load texture data from an SH-4 buffer into PVR RAM, twiddling it in the process
       //pvr_txr_load_ex((void *)out_buffer, out_buffer, XDIM, YDIM, PVR_TXRLOAD_16BPP);
       //pvr_txr_load_ex((void *)out_buffer, Image_data, XDIM, YDIM, PVR_TXRLOAD_16BPP);
       //out_buffer is the decoded frame stored in memory.

       // Create a textured polygon context
       pvr_poly_cxt_txr(&Image_context, PVR_LIST_OP_POLY, PVR_TXRFMT_YUV422 | PVR_TXRFMT_NONTWIDDLED, XDIM, YDIM, out_buffer, PVR_FILTER_TRILINEAR1);
       pvr_poly_compile(&Image_Header, &Image_context); // Convert the context into something the pvr can read
User avatar
PH3NOM
DC Developer
DC Developer
Posts: 576
Joined: Fri Jun 18, 2010 9:29 pm
Has thanked: 0
Been thanked: 5 times

Re: Drawing rgb565 image in output_buffer using PVR

Post by PH3NOM »

Forget about my last post - It seems that method worked on emulator, but not on real hardware.

My code now uses vo_txr_load by Josh Sutherland instead of any pvr_txr_load function.
It is very nice because it supports any resolution and is pretty much as fast as pvr_txr_load.

I am convinced I can achieve the speed to make the fastest XviD player ever seen on Dreamcast.
So, now I am working on reading packets from an AVI file.

I have implemented AVI packet reading into the XviD player.
Surprisingly, this brought a very nice speed boost, and works flawlessly.

I have also modified the KOS port of libmp3, to decode packets read from AVI instead of an MP3 file.
When decoding only the audio, the mp3 player will decode the entire stream read from the .avi file perfectly.
BUT, when decoding the video + audio simultaneously, It will only fill the audio buffer 1x, decode that data,
then exit on error "Bad Sync in MPEG file"

Does anyone have experience with the KOS libmp3, and have any ideas why this is happening?

Here is the modified code:

Code: Select all

/* Checks to make sure we have some data available in the bitstream
   buffer; if there's less than a certain "water level", shift the
   data back and bring in some more. */
static int bs_fill() {
	int n;

	/* Make sure we don't underflow */
	if (bs_count < 0) bs_count = 0;

	/* Pull in some more data if we need it */
	if (bs_count < BS_WATER) {
		/* Shift everything back */
		memcpy(bs_buffer, bs_ptr, bs_count);

		/* Read in some more data */
		// printf("fs_read(%d,%x,%d)\r\n", mp3_fd, bs_buffer+bs_count, BS_SIZE - bs_count);
		//n = fs_read(mp3_fd, bs_buffer+bs_count, BS_SIZE - bs_count);
		n = AVI_read_audio(mp3_fd, bs_buffer+bs_count, BS_SIZE - bs_count);
		
		// printf("==%d\r\n", n);
		if (n <= 0)
			return -1;

		/* Shift pointers back */
		bs_count += n; bs_ptr = bs_buffer;
	}

	return 0;
}

/* Empties out the last (now-used) frame of data from the PCM buffer */
static int pcm_empty(int size) {
	if (pcm_count >= size) {
		/* Shift everything back */
		memcpy(pcm_buffer, pcm_buffer + size, pcm_count - size);

		/* Shift pointers back */
		pcm_count -= size;
		pcm_ptr = pcm_buffer + pcm_count;
	}

	return 0;
}

/* This callback is called each time the sndstream driver needs
   some more data. It will tell us how much it needs in bytes. */
static void* xing_callback(snd_stream_hnd_t hnd, int size, int * actual) {
	static	int frames = 0;
	IN_OUT	x;

	/* Check for file not started or file finished */
	if (mp3_fd == 0)
		return NULL;

	/* Dump the last PCM packet */
	pcm_empty(pcm_discard);

	/* Loop decoding until we have a full buffer */
	while (pcm_count < size) {
		/* Pull in some more data (and check for EOF) */
		if (bs_fill() < 0 || bs_count < frame_bytes) {
			printf("Decode completed\r\n");
			goto errorout;
		}

		/* Decode a frame */
		
		x = audio_decode(&mpeg, bs_ptr, (short*)pcm_ptr);
		if (x.in_bytes <= 0) {
			printf("MP3 FATAL ERROR: Bad sync in MPEG file\r\n");
			goto errorout;
		}

		bs_ptr += x.in_bytes; bs_count -= x.in_bytes;
		pcm_ptr += x.out_bytes; pcm_count += x.out_bytes;
		
		frames++;
		/*if (!(frames % 64)) {
			printf("Decoded %d frames    \r", frames);
		}*/
	}

	pcm_discard = *actual = size;

	/* Got it successfully */
	return pcm_buffer;

errorout:
	fs_close(mp3_fd); mp3_fd = 0;
	return NULL;
}

/* Open an MPEG stream and prepare for decode */
static int xing_init(const char *fn) {
	uint32	fd;

	/* Open the file */
	//mp3_fd = fd = fs_open(fn, O_RDONLY);
	
	//mp3_fd = fd = AVI_open_input(fn, 1);
	
	mp3_fd = fd = fn;
	
	if (fd < 0) {
		printf("Can't open input file %s\r\n", fn);
		printf("getwd() returns '%s'\r\n", fs_getwd());
		return -1;
User avatar
PH3NOM
DC Developer
DC Developer
Posts: 576
Joined: Fri Jun 18, 2010 9:29 pm
Has thanked: 0
Been thanked: 5 times

Re: Drawing rgb565 image in output_buffer using PVR

Post by PH3NOM »

Sorry to bump my old topic seems its turning into a blog but I did solve the problem described in my last post.

My modifications to the KOS MP3 decoder were flawless.
All I had to do was create a mutex on the avi parser to maintain synch between a/v reads and everything is good now.

I have a complete running xvid/mp3 decoder that is the fastest and highest quality/compatibility I have seen on Dreamcast.
In fact, I have also ported LibMPEG2 and tested video decode/display speeds on elementary streams; no demuxing a/v or decoding audio.
I will give the source for LibMPEG2-DC away http://www.megaupload.com/?d=HH5WOSQ9
LibXviD is faster even while demuxing a/v and decoding a + v, even before the SH4 optimizations to the library.

I just need to add video synch code.
Using the XviD codec, the DTS and PTS timestamp codes are always identical, therefore its possible to maintain video synch by simply displaying the decoded image at the videos encoded frame rate.

I have attmpted to use the SDL_framerateDelay example included in KOS, but it does not seem to be 100% accurate, sometimes too fast sometimes too slow within the same process.

What is the best way to regulate video framerate in KOS without using SDL?
User avatar
Neoblast
DC Developer
DC Developer
Posts: 314
Joined: Sat Dec 01, 2007 8:51 am
Has thanked: 3 times
Been thanked: 1 time

Re: Drawing rgb565 image in output_buffer using PVR

Post by Neoblast »

PH3NOM wrote:Sorry to bump my old topic seems its turning into a blog but I did solve the problem described in my last post.

My modifications to the KOS MP3 decoder were flawless.
All I had to do was create a mutex on the avi parser to maintain synch between a/v reads and everything is good now.

I have a complete running xvid/mp3 decoder that is the fastest and highest quality/compatibility I have seen on Dreamcast.
In fact, I have also ported LibMPEG2 and tested video decode/display speeds on elementary streams; no demuxing a/v or decoding audio.
I will give the source for LibMPEG2-DC away http://www.megaupload.com/?d=HH5WOSQ9
LibXviD is faster even while demuxing a/v and decoding a + v, even before the SH4 optimizations to the library.

I just need to add video synch code.
Using the XviD codec, the DTS and PTS timestamp codes are always identical, therefore its possible to maintain video synch by simply displaying the decoded image at the videos encoded frame rate.

I have attmpted to use the SDL_framerateDelay example included in KOS, but it does not seem to be 100% accurate, sometimes too fast sometimes too slow within the same process.

What is the best way to regulate video framerate in KOS without using SDL?
Awesome man, we just placed a mirror on our site so it doesn't get lost.
Does it support audio?
How fast is libxvid compared to the last one ported to dc?
User avatar
PH3NOM
DC Developer
DC Developer
Posts: 576
Joined: Fri Jun 18, 2010 9:29 pm
Has thanked: 0
Been thanked: 5 times

Re: Drawing rgb565 image in output_buffer using PVR

Post by PH3NOM »

LibMPEG2 only handles mpeg1/mpeg2 video; it requires another library for audio decoding.
I havnt spent much time with LibMPEG2; the source code I uploaded only supports decoding .m1v/.m2v elementary video streams on Dreamcast.

All of the source I have looked at for Dreamcast divx players are actually based on FFMPEG.
"XviD-DC", the player im working on is based on LibXviD which is much simpler and more efficient.
It also supports all/current versions of the xvid/divx codec.

To give an idea of XviD-DC current speed:
A test clip 94 seconds ( tv show "Always sunny in Philadelphia")
Video: DivX @ 480x272(1:1 PAR = 480x272 DAR) , 1Mbps, 23.97fps
Audio: MP3 @ 48kHz, 2ch stereo, 128kbps
Decode completed in 89 seconds.

Video: DivX @ 448x304 (16:9 PAR = 540x304 DAR), 1Mbps, 23.97fps
Audio: MP3 @ 48kHz, 2ch stereo, 128kbps
Decode completed in 91 seconds.

Back to working on video synch code:
I am working on a method using <arch/timer.h>
Ive made a small function:

Code: Select all

int dc_get_time( ) {
    
    uint32 s, ms;
	uint64 msec;

	timer_ms_gettime(&s, &ms);
	msec = (((uint64)s) * ((uint64)1000)) + ((uint64)ms);

	return (int)msec;
}
to accurately record how long the entire decode process takes. I am still working on implementing it for frame-rate regulation.

The basic idea of my algorithm for maintaining video frame-rate is simple;
Record start and end time of frame decoding(dt) using dc_get_time().
Compare that time to the required frame rate(fr).
If decode time is less than frame rate, if ( dt < fr ), then thd_sleep ( fr - dt ).
If ( dt > fr ), then skip next frame && thd_sleep( fr - ( dt - fr ) ).
In its most advanced stage it will monitor current frame number and overall decode time to be most precise.
User avatar
Neoblast
DC Developer
DC Developer
Posts: 314
Joined: Sat Dec 01, 2007 8:51 am
Has thanked: 3 times
Been thanked: 1 time

Re: Drawing rgb565 image in output_buffer using PVR

Post by Neoblast »

PH3NOM wrote:LibMPEG2 only handles mpeg1/mpeg2 video; it requires another library for audio decoding.
I havnt spent much time with LibMPEG2; the source code I uploaded only supports decoding .m1v/.m2v elementary video streams on Dreamcast.

All of the source I have looked at for Dreamcast divx players are actually based on FFMPEG.
"XviD-DC", the player im working on is based on LibXviD which is much simpler and more efficient.
It also supports all/current versions of the xvid/divx codec.

To give an idea of XviD-DC current speed:
A test clip 94 seconds ( tv show "Always sunny in Philadelphia")
Video: DivX @ 480x272(1:1 PAR = 480x272 DAR) , 1Mbps, 23.97fps
Audio: MP3 @ 48kHz, 2ch stereo, 128kbps
Decode completed in 89 seconds.

Video: DivX @ 448x304 (16:9 PAR = 540x304 DAR), 1Mbps, 23.97fps
Audio: MP3 @ 48kHz, 2ch stereo, 128kbps
Decode completed in 91 seconds.

Back to working on video synch code:
I am working on a method using <arch/timer.h>
Ive made a small function:

Code: Select all

int dc_get_time( ) {
    
    uint32 s, ms;
	uint64 msec;

	timer_ms_gettime(&s, &ms);
	msec = (((uint64)s) * ((uint64)1000)) + ((uint64)ms);

	return (int)msec;
}
to accurately record how long the entire decode process takes. I am still working on implementing it for frame-rate regulation.

The basic idea of my algorithm for maintaining video frame-rate is simple;
Record start and end time of frame decoding(dt) using dc_get_time().
Compare that time to the required frame rate(fr).
If decode time is less than frame rate, if ( dt < fr ), then thd_sleep ( fr - dt ).
If ( dt > fr ), then skip next frame && thd_sleep( fr - ( dt - fr ) ).
In its most advanced stage it will monitor current frame number and overall decode time to be most precise.
Impressive, so the average fps will be around 24.
That's more or less what I get when playing regular xvids on my pc with a little less resolution.

That's way better than the mpeg libs used in the official sdks 10 years ago, which had less resolution, less fps and overall worse quality.
Post Reply