DCEmulation

dreamcast development • homebrew software • hardware hacking • indie games • emulators • and more!
Back to main site
It is currently Wed Oct 01, 2014 9:23 pm

All times are UTC - 8 hours [ DST ]




Post new topic Reply to topic  [ 29 posts ]  Go to page 1, 2  Next
Author Message
PostPosted: Sat Jul 17, 2010 4:23 pm 
Offline
DC Developer
DC Developer
User avatar

Joined: Fri Jun 18, 2010 7:29 pm
Posts: 410
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!


Top
 Profile  
 
PostPosted: Sat Jul 17, 2010 5:40 pm 
Offline
Insane DCEmu
Insane DCEmu

Joined: Thu Mar 29, 2007 10:09 pm
Posts: 152
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:
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.


Top
 Profile  
 
PostPosted: Sat Jul 17, 2010 7:08 pm 
Offline
DC Developer
DC Developer
User avatar

Joined: Fri Jun 18, 2010 7:29 pm
Posts: 410
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:
//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


Top
 Profile  
 
PostPosted: Sun Jul 18, 2010 2:19 am 
Offline
Insane DCEmu
Insane DCEmu

Joined: Thu Mar 29, 2007 10:09 pm
Posts: 152
PH3NOM wrote:
I think my problem is Im not sure exactly what parameter to pass here.
Code:
//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:
// 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?


Top
 Profile  
 
PostPosted: Sun Jul 18, 2010 12:20 pm 
Offline
DC Developer
DC Developer
User avatar

Joined: Fri Jun 18, 2010 7:29 pm
Posts: 410
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:
         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:
         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:
out_buffer = (unsigned char*)malloc(XDIM*YDIM*4);


Top
 Profile  
 
PostPosted: Sun Jul 18, 2010 1:22 pm 
Offline
The Crabby Overlord
The Crabby Overlord
User avatar

Joined: Mon May 27, 2002 9:31 am
Posts: 4189
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:
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:
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);


Top
 Profile  
 
PostPosted: Sun Jul 18, 2010 2:34 pm 
Offline
Insane DCEmu
Insane DCEmu

Joined: Thu Mar 29, 2007 10:09 pm
Posts: 152
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:
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:
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);


Top
 Profile  
 
PostPosted: Sun Jul 18, 2010 4:28 pm 
Offline
The Crabby Overlord
The Crabby Overlord
User avatar

Joined: Mon May 27, 2002 9:31 am
Posts: 4189
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:
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:
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:


Top
 Profile  
 
PostPosted: Sun Jul 18, 2010 7:52 pm 
Offline
DC Developer
DC Developer
User avatar

Joined: Fri Jun 18, 2010 7:29 pm
Posts: 410
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:
/////////////////////////////////////////////////////////////
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?


Top
 Profile  
 
PostPosted: Sun Jul 18, 2010 8:52 pm 
Offline
The Crabby Overlord
The Crabby Overlord
User avatar

Joined: Mon May 27, 2002 9:31 am
Posts: 4189
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).


Top
 Profile  
 
PostPosted: Tue Jul 20, 2010 10:19 pm 
Offline
DC Developer
DC Developer
User avatar

Joined: Fri Jun 18, 2010 7:29 pm
Posts: 410
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...


Top
 Profile  
 
PostPosted: Wed Jul 21, 2010 8:50 pm 
Offline
Insane DCEmu
Insane DCEmu

Joined: Thu Mar 29, 2007 10:09 pm
Posts: 152
Probably should have told you that in the beginning: viewtopic.php?p=1009854#p1009854

Did you do any DMA stuff yet?


Top
 Profile  
 
PostPosted: Thu Jul 22, 2010 7:28 am 
Offline
DC Developer
DC Developer
User avatar

Joined: Fri Jun 18, 2010 7:29 pm
Posts: 410
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...


Top
 Profile  
 
PostPosted: Thu Jul 22, 2010 3:47 pm 
Offline
The Crabby Overlord
The Crabby Overlord
User avatar

Joined: Mon May 27, 2002 9:31 am
Posts: 4189
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).


Top
 Profile  
 
PostPosted: Fri Jul 23, 2010 11:55 am 
Offline
DC Developer
DC Developer
User avatar

Joined: Fri Jun 18, 2010 7:29 pm
Posts: 410
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:
               /* 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:
       // 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


Top
 Profile  
 
PostPosted: Sun Aug 15, 2010 11:28 am 
Offline
DC Developer
DC Developer
User avatar

Joined: Fri Jun 18, 2010 7:29 pm
Posts: 410
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:
/* 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;


Top
 Profile  
 
PostPosted: Thu Feb 10, 2011 8:58 pm 
Offline
DC Developer
DC Developer
User avatar

Joined: Fri Jun 18, 2010 7:29 pm
Posts: 410
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?


Top
 Profile  
 
PostPosted: Sun Feb 27, 2011 3:00 pm 
Offline
DC Developer
DC Developer
User avatar

Joined: Sat Dec 01, 2007 7:51 am
Posts: 295
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?


Top
 Profile  
 
PostPosted: Mon Feb 28, 2011 9:10 pm 
Offline
DC Developer
DC Developer
User avatar

Joined: Fri Jun 18, 2010 7:29 pm
Posts: 410
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:
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.


Top
 Profile  
 
PostPosted: Tue Mar 01, 2011 7:25 am 
Offline
DC Developer
DC Developer
User avatar

Joined: Sat Dec 01, 2007 7:51 am
Posts: 295
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:
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.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 29 posts ]  Go to page 1, 2  Next

All times are UTC - 8 hours [ DST ]


Who is online

Users browsing this forum: No registered users and 1 guest


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
cron
Powered by phpBB® Forum Software © phpBB Group