Drawing rgb565 image in output_buffer using PVR
- PH3NOM
- 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
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!
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!
- BB Hood
- 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
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):
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.
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();
Check out pvr.h in the "\usr\local\dc\kos\kos\kernel\arch\dreamcast\include\dc" directory for more help.
- PH3NOM
- 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
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.
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!
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.
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!
- BB Hood
- 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
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:I think my problem is Im not sure exactly what parameter to pass here.Is it the name of the variable that represents the location in memory?Code: Select all
//rawimagedata is the image data you have stored in memory.
Thats my fault. The last vertex submit was incorrect. Replace with this: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.
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);
- PH3NOM
- 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
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:
Here are the other colorspace profiles built in the decoder, I think RGB 16bit is the only one DC can accept?:
And the buffer is set up like this:
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;
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;
Code: Select all
out_buffer = (unsigned char*)malloc(XDIM*YDIM*4);
- BlueCrab
- 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
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:
and change it to:
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);
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);
- BB Hood
- 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
Wouldn't the pvr_txr_load_ex() function twiddle it for him?BlueCrab wrote: I seriously doubt you're using a twiddled texture (as the example code that was posted assumed).
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);
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);
- BlueCrab
- 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
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.BB Hood wrote:Wouldn't the pvr_txr_load_ex() function twiddle it for him?BlueCrab wrote: I seriously doubt you're using a twiddled texture (as the example code that was posted assumed).
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_NONTWIDDLED, Image_width, Image_height, Image_data, PVR_FILTER_BILINEAR);
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);
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.
- PH3NOM
- 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
Awesome News!
I have got the decoder drawing every decoded frame with the help here!
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:
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?
I have got the decoder drawing every decoded frame with the help here!
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();
///////////////////////////////////////////////////////////
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?
- BlueCrab
- 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
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).
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).
- PH3NOM
- 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
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...
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...
- BB Hood
- 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
Probably should have told you that in the beginning: viewtopic.php?p=1009854#p1009854
Did you do any DMA stuff yet?
Did you do any DMA stuff yet?
- PH3NOM
- 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
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...
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...
- BlueCrab
- 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
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).
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).
- PH3NOM
- 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
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.
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
- PH3NOM
- 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
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:
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;
- PH3NOM
- 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
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?
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?
- Neoblast
- 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
Awesome man, we just placed a mirror on our site so it doesn't get lost.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?
Does it support audio?
How fast is libxvid compared to the last one ported to dc?
- PH3NOM
- 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
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:
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.
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;
}
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.
- Neoblast
- 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
Impressive, so the average fps will be around 24.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:
to accurately record how long the entire decode process takes. I am still working on implementing it for frame-rate regulation.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; }
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.
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.