Thank you so much for this! It will be fantastic to have this immediately available to all KOS users.
pl_mpegDC ported running but community help needed
-
- DCEmu Webmaster
- Posts: 16394
- https://www.artistsworkshop.eu/meble-kuchenne-na-wymiar-warszawa-gdzie-zamowic/
- Joined: Wed Mar 14, 2001 6:00 pm
- Location: New Orleans, LA
- Has thanked: 128 times
- Been thanked: 92 times
- Contact:
Re: pl_mpegDC ported running but community help needed
- These users thanked the author |darc| for the post (total 2):
- Ian Robinson • Twada
It's thinking...
-
- DC Developer
- Posts: 48
- Joined: Wed Jan 20, 2016 4:55 am
- Has thanked: 20 times
- Been thanked: 56 times
Re: pl_mpegDC ported running but community help needed
I think it's possible.Ian Robinson wrote: ↑Wed Sep 20, 2023 8:46 am Do you think with this it would be possible to add function for pause/resume a movie ? ..
mpeg1.c is a short code just for playback, but pl_mpeg.h is optimized, so it should be possible if you create a suitable wrapper.
Until recently, I hadn't put pvr_wait_ready in the right place, which seems to have added more load than it should have. It probably has enough power to display the UI of the video player as well.
However, I haven't touched plm_seek at all, so I won't know about seek processing until I try it. In that case, you still need to rewrite the sound callback.
That's great news!GyroVorbis wrote: ↑Wed Sep 20, 2023 2:57 pm Oh yeah, this is totally expected. After all, you just barely got the thing up and working! I figured there would be some polishing that would need to be done. I've added a task to the KOS backlog for helping to get this ready to be added as a KOS-Port!
- These users thanked the author Twada for the post:
- Ian Robinson
- Ian Robinson
- DC Developer
- Posts: 126
- Joined: Mon Mar 11, 2019 7:12 am
- Has thanked: 225 times
- Been thanked: 45 times
Re: pl_mpegDC ported running but community help needed
Ok i worked on tighter frame control and resetting the sound call back and adding a buffer to keep it more in sync on longer videos
Here are the changes look it over for me ..
seems to be working correct. always good to have other eyes. I notice running from a cdr not /rd/ the audio getting out of sync and out of no where it gets super slow. So far this fixes this problem.
also for a cdr
Here are the changes look it over for me ..
Code: Select all
#include <kos.h>
#define PL_MPEG_IMPLEMENTATION
#include "pl_mpeg.h"
#include "mpeg1.h"
static plm_t *plm;
/* textures */
static pvr_ptr_t texture;
static int width, height;
// Output texture width and height initial values
// You can choose from 32, 64, 128, 256, 512, 1024
#define MPEG1_TEXTURE_WIDTH 512
#define MPEG1_TEXTURE_HEIGHT 256
snd_stream_hnd_t snd_hnd;
__attribute__((aligned(32))) unsigned int snd_buf[0x10000 / 4];
void display_draw(void)
{
pvr_poly_cxt_t cxt;
pvr_poly_hdr_t hdr;
pvr_vertex_t vert;
float u = (float)width / (float)MPEG1_TEXTURE_WIDTH;
float v = (float)height / (float)MPEG1_TEXTURE_HEIGHT;
pvr_poly_cxt_txr(&cxt, PVR_LIST_OP_POLY, PVR_TXRFMT_YUV422 | PVR_TXRFMT_NONTWIDDLED, MPEG1_TEXTURE_WIDTH, MPEG1_TEXTURE_HEIGHT, texture, PVR_FILTER_BILINEAR);
pvr_poly_compile(&hdr, &cxt);
// hdr.mode3 |= 0x02000000; /* stride */
pvr_prim(&hdr, sizeof(hdr));
vert.argb = PVR_PACK_COLOR(1.0f, 1.0f, 1.0f, 1.0f);
vert.oargb = 0;
vert.flags = PVR_CMD_VERTEX;
vert.x = 1;
vert.y = 1;
vert.z = 1;
vert.u = 0.0f;
vert.v = 0.0f;
pvr_prim(&vert, sizeof(vert));
vert.x = 640;
vert.y = 1;
vert.z = 1;
vert.u = u;
vert.v = 0.0;
pvr_prim(&vert, sizeof(vert));
vert.x = 1;
vert.y = 480;
vert.z = 1;
vert.u = 0.0f;
vert.v = v;
pvr_prim(&vert, sizeof(vert));
vert.x = 640;
vert.y = 480;
vert.z = 1;
vert.u = u;
vert.v = v;
vert.flags = PVR_CMD_VERTEX_EOL;
pvr_prim(&vert, sizeof(vert));
}
void app_on_video(plm_t *mpeg, plm_frame_t *frame, void *user)
{
unsigned int *dest = (unsigned int *)texture;
unsigned int *src = (unsigned int *)frame->display;
volatile unsigned int *d = (volatile unsigned int *)0xa05f8148;
volatile unsigned int *cfg = (volatile unsigned int *)0xa05f814c;
volatile unsigned int *stride_reg = (volatile unsigned int *)0xa05f80e4;
int stride_value;
int stride = 0;
int x, y, w, h, i;
if (!frame)
return;
/* set frame size. */
w = frame->width >> 4;
h = frame->height >> 4;
stride_value = (w >> 1); /* 16 pixel / 2 */
/* Set Stride value. */
*stride_reg &= 0xffffffe0;
*stride_reg |= stride_value & 0x01f;
/* Set SQ to YUV converter. */
*d = ((unsigned int)dest) & 0xffffff;
*cfg = 0x00000f1f;
x = *cfg; /* read on once */
for (y = 0; y < h; y++)
{
for (x = 0; x < w; x++, src += 96)
{
sq_cpy((void *)0x10800000, (void *)src, 384);
}
if (!stride)
{
/* Send dummy mb */
for (i = 0; i < 32 - w; i++)
{
sq_set((void *)0x10800000, 0, 384);
}
}
}
for (i = 0; i < 16 - h; i++)
{
if (!stride)
sq_set((void *)0x10800000, 0, 384 * 32);
else
sq_set((void *)0x10800000, 0, 384 * w);
}
}
// Define a buffer for audio samples
#define AUDIO_SAMPLE_BUFFER_SIZE (1152 * 2 * 10) // Adjust the size as needed
// Static variables for sound callback
static int mod_start = 0;
static int mod_size = 0;
static unsigned int audio_sample_buffer[AUDIO_SAMPLE_BUFFER_SIZE];
// Function to reset sound callback's static variables
void reset_sound_callback()
{
mod_start = 0;
mod_size = 0;
}
// Sound callback function
void *sound_callback(snd_stream_hnd_t hnd, int size, int *size_out)
{
unsigned int *dest = audio_sample_buffer;
unsigned int *src;
int out = 0;
src = audio_sample_buffer + mod_start / 4;
for (int i = 0; i < mod_size / 4; i++)
*dest++ = *src++;
out += mod_size;
while (size > out)
{
plm_samples_t *sample = plm_decode_audio(plm);
if (sample == NULL)
{
reset_sound_callback(); // Reset static variables when audio ends
break;
}
src = (unsigned int *)sample->pcm;
for (int i = 0; i < 1152 / 2; i++)
*dest++ = *src++;
out += 1152 * 2;
}
mod_start = size;
mod_size = out - size;
*size_out = size;
return (void *)audio_sample_buffer;
}
int Mpeg1Play(const char *filename, unsigned int buttons)
{
int cancel = 0;
plm = plm_create_with_filename(filename);
if (!plm)
return -1;
texture = pvr_mem_malloc(512 * 256 * 2);
width = plm_get_width(plm);
height = plm_get_height(plm);
/* Set SQ to YUV converter. */
PVR_SET(PVR_YUV_ADDR, (((unsigned int)texture) & 0xffffff));
// Divide texture width and texture height by 16 and subtract 1.
// The actual values to set are 1, 3, 7, 15, 31, 63.
PVR_SET(PVR_YUV_CFG_1, (((MPEG1_TEXTURE_HEIGHT / 16) - 1) << 8) | ((MPEG1_TEXTURE_WIDTH / 16) - 1));
PVR_GET(PVR_YUV_CFG_1);
/* First frame */
plm_frame_t *frame = plm_decode_video(plm);
float start_time = (float)timer_ms_gettime64() / 1000.0;
float playing_time = 0.0f;
float frame_time = 1.0f / (float)plm_get_framerate(plm);
int decoded = 1;
/* Init sound stream. */
int samplerate = plm_get_samplerate(plm);
snd_hnd = snd_stream_alloc(sound_callback, 0x10000);
snd_stream_volume(snd_hnd, 0xff);
snd_stream_queue_enable(snd_hnd);
snd_stream_start(snd_hnd, samplerate, 0);
snd_stream_queue_go(snd_hnd);
while (!cancel)
{
/* Check cancel buttons. */
if (buttons)
{
MAPLE_FOREACH_BEGIN(MAPLE_FUNC_CONTROLLER, cont_state_t, st)
if ((st->buttons & buttons) == buttons)
cancel = 1;
MAPLE_FOREACH_END()
}
/* Decode */
playing_time = ((float)timer_ms_gettime64() / 1000.0) - start_time;
if ((frame->time - playing_time) < frame_time)
{
frame = plm_decode_video(plm);
if (!frame)
break;
decoded = 1;
}
snd_stream_poll(snd_hnd);
/* Render */
pvr_wait_ready();
pvr_scene_begin();
if (decoded)
{
app_on_video(plm, frame, 0);
decoded = 0;
}
pvr_list_begin(PVR_LIST_OP_POLY);
display_draw();
pvr_list_finish();
pvr_scene_finish();
}
plm_destroy(plm);
pvr_mem_free(texture);
snd_stream_destroy(snd_hnd);
return 0;
}
also for a cdr
Code: Select all
ffmpeg -i input.mp4 -vf "scale=320:240" -b:v 800k -ac 1 -ar 44100 -b:a 80k -f mpeg output.mpeg
- These users thanked the author Ian Robinson for the post:
- |darc|
-
- DC Developer
- Posts: 48
- Joined: Wed Jan 20, 2016 4:55 am
- Has thanked: 20 times
- Been thanked: 56 times
Re: pl_mpegDC ported running but community help needed
Thank you for the necessary correction.Ian Robinson wrote: ↑Thu Sep 21, 2023 9:37 am Ok i worked on tighter frame control and resetting the sound call back and adding a buffer to keep it more in sync on longer videos
Here are the changes look it over for me ..
seems to be working correct. always good to have other eyes. I notice running from a cdr not /rd/ the audio getting out of sync and out of no where it gets super slow. So far this fixes this problem.Code: Select all
#include <kos.h> #define PL_MPEG_IMPLEMENTATION #include "pl_mpeg.h" #include "mpeg1.h" static plm_t *plm; /* textures */ static pvr_ptr_t texture; static int width, height; // Output texture width and height initial values // You can choose from 32, 64, 128, 256, 512, 1024 #define MPEG1_TEXTURE_WIDTH 512 #define MPEG1_TEXTURE_HEIGHT 256 snd_stream_hnd_t snd_hnd; __attribute__((aligned(32))) unsigned int snd_buf[0x10000 / 4]; void display_draw(void) { pvr_poly_cxt_t cxt; pvr_poly_hdr_t hdr; pvr_vertex_t vert; float u = (float)width / (float)MPEG1_TEXTURE_WIDTH; float v = (float)height / (float)MPEG1_TEXTURE_HEIGHT; pvr_poly_cxt_txr(&cxt, PVR_LIST_OP_POLY, PVR_TXRFMT_YUV422 | PVR_TXRFMT_NONTWIDDLED, MPEG1_TEXTURE_WIDTH, MPEG1_TEXTURE_HEIGHT, texture, PVR_FILTER_BILINEAR); pvr_poly_compile(&hdr, &cxt); // hdr.mode3 |= 0x02000000; /* stride */ pvr_prim(&hdr, sizeof(hdr)); vert.argb = PVR_PACK_COLOR(1.0f, 1.0f, 1.0f, 1.0f); vert.oargb = 0; vert.flags = PVR_CMD_VERTEX; vert.x = 1; vert.y = 1; vert.z = 1; vert.u = 0.0f; vert.v = 0.0f; pvr_prim(&vert, sizeof(vert)); vert.x = 640; vert.y = 1; vert.z = 1; vert.u = u; vert.v = 0.0; pvr_prim(&vert, sizeof(vert)); vert.x = 1; vert.y = 480; vert.z = 1; vert.u = 0.0f; vert.v = v; pvr_prim(&vert, sizeof(vert)); vert.x = 640; vert.y = 480; vert.z = 1; vert.u = u; vert.v = v; vert.flags = PVR_CMD_VERTEX_EOL; pvr_prim(&vert, sizeof(vert)); } void app_on_video(plm_t *mpeg, plm_frame_t *frame, void *user) { unsigned int *dest = (unsigned int *)texture; unsigned int *src = (unsigned int *)frame->display; volatile unsigned int *d = (volatile unsigned int *)0xa05f8148; volatile unsigned int *cfg = (volatile unsigned int *)0xa05f814c; volatile unsigned int *stride_reg = (volatile unsigned int *)0xa05f80e4; int stride_value; int stride = 0; int x, y, w, h, i; if (!frame) return; /* set frame size. */ w = frame->width >> 4; h = frame->height >> 4; stride_value = (w >> 1); /* 16 pixel / 2 */ /* Set Stride value. */ *stride_reg &= 0xffffffe0; *stride_reg |= stride_value & 0x01f; /* Set SQ to YUV converter. */ *d = ((unsigned int)dest) & 0xffffff; *cfg = 0x00000f1f; x = *cfg; /* read on once */ for (y = 0; y < h; y++) { for (x = 0; x < w; x++, src += 96) { sq_cpy((void *)0x10800000, (void *)src, 384); } if (!stride) { /* Send dummy mb */ for (i = 0; i < 32 - w; i++) { sq_set((void *)0x10800000, 0, 384); } } } for (i = 0; i < 16 - h; i++) { if (!stride) sq_set((void *)0x10800000, 0, 384 * 32); else sq_set((void *)0x10800000, 0, 384 * w); } } // Define a buffer for audio samples #define AUDIO_SAMPLE_BUFFER_SIZE (1152 * 2 * 10) // Adjust the size as needed // Static variables for sound callback static int mod_start = 0; static int mod_size = 0; static unsigned int audio_sample_buffer[AUDIO_SAMPLE_BUFFER_SIZE]; // Function to reset sound callback's static variables void reset_sound_callback() { mod_start = 0; mod_size = 0; } // Sound callback function void *sound_callback(snd_stream_hnd_t hnd, int size, int *size_out) { unsigned int *dest = audio_sample_buffer; unsigned int *src; int out = 0; src = audio_sample_buffer + mod_start / 4; for (int i = 0; i < mod_size / 4; i++) *dest++ = *src++; out += mod_size; while (size > out) { plm_samples_t *sample = plm_decode_audio(plm); if (sample == NULL) { reset_sound_callback(); // Reset static variables when audio ends break; } src = (unsigned int *)sample->pcm; for (int i = 0; i < 1152 / 2; i++) *dest++ = *src++; out += 1152 * 2; } mod_start = size; mod_size = out - size; *size_out = size; return (void *)audio_sample_buffer; } int Mpeg1Play(const char *filename, unsigned int buttons) { int cancel = 0; plm = plm_create_with_filename(filename); if (!plm) return -1; texture = pvr_mem_malloc(512 * 256 * 2); width = plm_get_width(plm); height = plm_get_height(plm); /* Set SQ to YUV converter. */ PVR_SET(PVR_YUV_ADDR, (((unsigned int)texture) & 0xffffff)); // Divide texture width and texture height by 16 and subtract 1. // The actual values to set are 1, 3, 7, 15, 31, 63. PVR_SET(PVR_YUV_CFG_1, (((MPEG1_TEXTURE_HEIGHT / 16) - 1) << 8) | ((MPEG1_TEXTURE_WIDTH / 16) - 1)); PVR_GET(PVR_YUV_CFG_1); /* First frame */ plm_frame_t *frame = plm_decode_video(plm); float start_time = (float)timer_ms_gettime64() / 1000.0; float playing_time = 0.0f; float frame_time = 1.0f / (float)plm_get_framerate(plm); int decoded = 1; /* Init sound stream. */ int samplerate = plm_get_samplerate(plm); snd_hnd = snd_stream_alloc(sound_callback, 0x10000); snd_stream_volume(snd_hnd, 0xff); snd_stream_queue_enable(snd_hnd); snd_stream_start(snd_hnd, samplerate, 0); snd_stream_queue_go(snd_hnd); while (!cancel) { /* Check cancel buttons. */ if (buttons) { MAPLE_FOREACH_BEGIN(MAPLE_FUNC_CONTROLLER, cont_state_t, st) if ((st->buttons & buttons) == buttons) cancel = 1; MAPLE_FOREACH_END() } /* Decode */ playing_time = ((float)timer_ms_gettime64() / 1000.0) - start_time; if ((frame->time - playing_time) < frame_time) { frame = plm_decode_video(plm); if (!frame) break; decoded = 1; } snd_stream_poll(snd_hnd); /* Render */ pvr_wait_ready(); pvr_scene_begin(); if (decoded) { app_on_video(plm, frame, 0); decoded = 0; } pvr_list_begin(PVR_LIST_OP_POLY); display_draw(); pvr_list_finish(); pvr_scene_finish(); } plm_destroy(plm); pvr_mem_free(texture); snd_stream_destroy(snd_hnd); return 0; }
also for a cdrCode: Select all
ffmpeg -i input.mp4 -vf "scale=320:240" -b:v 800k -ac 1 -ar 44100 -b:a 80k -f mpeg output.mpeg
I was concerned that if I stop the video in the middle without playing it to the end, the previous mod_start and mod_size may remain.
How about making sure to call reset_sound_callback() before initializing the sound stream?
(Actually, I wanted to implement a cool ring buffer instead of copying data. Hahaha)
And thank you for verifying the bitrate.
If the video and audio reading positions are too far apart due to processing delays, the loading becomes very complicated and seems to hang.
It certainly seems like 800kbps is a reasonable size. It was helpful.
- These users thanked the author Twada for the post:
- Ian Robinson
- Ian Robinson
- DC Developer
- Posts: 126
- Joined: Mon Mar 11, 2019 7:12 am
- Has thanked: 225 times
- Been thanked: 45 times
Re: pl_mpegDC ported running but community help needed
Ok this played my test video and stayed on sync
correct me where i went wrong right now it's the first time it played
the matrix trailer and did not slow down
example.c
Names starting with Z are the fastest when dummied.
Before these changes the music would always complete first. Ok still a few places it goes out of sync but much better https://streamable.com/qtn6s4 .. I have done the ring buffer thing before i will see what i can do with that.. Threading did not make it better i tried and it made it crash all the time.. 5 hours wasted!
I will leave your version and not update it till you say so i made a folder with the work today now exits to dcload serial when the video ends it did not before.
https://github.com/ianmicheal/MPEG1-Dec ... updates%5D marked where the changes are in this folder.
Developing a cdrom/gdrom benchmark tool which will show you all speeds of all files on the disc almost done..It benchmarks the disc captures the log to the vmu and can read back with the pvr log viewer with scrolling..
Toolmenu https://streamable.com/5ub9iz
Pvr vmu log viewer https://streamable.com/eb2sp9
Benchmark menu https://streamable.com/lrn7av
It will load the texture of the game benchmark then save to the vmu..
I did this to see speed on a cdr where the best place and names are for media files..There is a very big change depending on how you create and order the files.
correct me where i went wrong right now it's the first time it played
the matrix trailer and did not slow down
Code: Select all
#include <kos.h>
#define PL_MPEG_IMPLEMENTATION
#include "pl_mpeg.h"
#include "mpeg1.h"
static plm_t *plm;
/* textures */
static pvr_ptr_t texture;
static int width, height;
// Output texture width and height initial values
// You can choose from 32, 64, 128, 256, 512, 1024
#define MPEG1_TEXTURE_WIDTH 512
#define MPEG1_TEXTURE_HEIGHT 256
snd_stream_hnd_t snd_hnd;
__attribute__((aligned(32))) unsigned int snd_buf[0x10000 / 4];
void display_draw(void)
{
pvr_poly_cxt_t cxt;
pvr_poly_hdr_t hdr;
pvr_vertex_t vert;
float u = (float)width / (float)MPEG1_TEXTURE_WIDTH;
float v = (float)height / (float)MPEG1_TEXTURE_HEIGHT;
pvr_poly_cxt_txr(&cxt, PVR_LIST_OP_POLY, PVR_TXRFMT_YUV422 | PVR_TXRFMT_NONTWIDDLED, MPEG1_TEXTURE_WIDTH, MPEG1_TEXTURE_HEIGHT, texture, PVR_FILTER_BILINEAR);
pvr_poly_compile(&hdr, &cxt);
// hdr.mode3 |= 0x02000000; /* stride */
pvr_prim(&hdr, sizeof(hdr));
vert.argb = PVR_PACK_COLOR(1.0f, 1.0f, 1.0f, 1.0f);
vert.oargb = 0;
vert.flags = PVR_CMD_VERTEX;
vert.x = 1;
vert.y = 1;
vert.z = 1;
vert.u = 0.0f;
vert.v = 0.0f;
pvr_prim(&vert, sizeof(vert));
vert.x = 640;
vert.y = 1;
vert.z = 1;
vert.u = u;
vert.v = 0.0;
pvr_prim(&vert, sizeof(vert));
vert.x = 1;
vert.y = 480;
vert.z = 1;
vert.u = 0.0f;
vert.v = v;
pvr_prim(&vert, sizeof(vert));
vert.x = 640;
vert.y = 480;
vert.z = 1;
vert.u = u;
vert.v = v;
vert.flags = PVR_CMD_VERTEX_EOL;
pvr_prim(&vert, sizeof(vert));
}
void app_on_video(plm_t *mpeg, plm_frame_t *frame, void *user)
{
unsigned int *dest = (unsigned int *)texture;
unsigned int *src = (unsigned int *)frame->display;
volatile unsigned int *d = (volatile unsigned int *)0xa05f8148;
volatile unsigned int *cfg = (volatile unsigned int *)0xa05f814c;
volatile unsigned int *stride_reg = (volatile unsigned int *)0xa05f80e4;
int stride_value;
int stride = 0;
int x, y, w, h, i;
if (!frame)
return;
/* set frame size. */
w = frame->width >> 4;
h = frame->height >> 4;
stride_value = (w >> 1); /* 16 pixel / 2 */
/* Set Stride value. */
*stride_reg &= 0xffffffe0;
*stride_reg |= stride_value & 0x01f;
/* Set SQ to YUV converter. */
*d = ((unsigned int)dest) & 0xffffff;
*cfg = 0x00000f1f;
x = *cfg; /* read on once */
for (y = 0; y < h; y++)
{
for (x = 0; x < w; x++, src += 96)
{
sq_cpy((void *)0x10800000, (void *)src, 384);
}
if (!stride)
{
/* Send dummy mb */
for (i = 0; i < 32 - w; i++)
{
sq_set((void *)0x10800000, 0, 384);
}
}
}
for (i = 0; i < 16 - h; i++)
{
if (!stride)
sq_set((void *)0x10800000, 0, 384 * 32);
else
sq_set((void *)0x10800000, 0, 384 * w);
}
}
// Define a buffer for audio samples
#define AUDIO_SAMPLE_BUFFER_SIZE (1152 * 2 * 10) // Adjust the size as needed
// Static variables for sound callback
static int mod_start = 0;
static int mod_size = 0;
static unsigned int audio_sample_buffer[AUDIO_SAMPLE_BUFFER_SIZE];
// Function to reset sound callback's static variables
void reset_sound_callback()
{
mod_start = 0;
mod_size = 0;
}
// Sound callback function
void *sound_callback(snd_stream_hnd_t hnd, int size, int *size_out)
{
unsigned int *dest = audio_sample_buffer;
unsigned int *src;
int out = 0;
src = audio_sample_buffer + mod_start / 4;
for (int i = 0; i < mod_size / 4; i++)
*dest++ = *src++;
out += mod_size;
while (size > out)
{
plm_samples_t *sample = plm_decode_audio(plm);
if (sample == NULL)
{
reset_sound_callback(); // Reset static variables when audio ends
break;
}
src = (unsigned int *)sample->pcm;
for (int i = 0; i < 1152 / 2; i++)
*dest++ = *src++;
out += 1152 * 2;
}
mod_start = size;
mod_size = out - size;
*size_out = size;
return (void *)audio_sample_buffer;
}
int Mpeg1Play(const char *filename, unsigned int buttons)
{
int cancel = 0;
plm = plm_create_with_filename(filename);
if (!plm)
return -1;
texture = pvr_mem_malloc(512 * 256 * 2);
width = plm_get_width(plm);
height = plm_get_height(plm);
/* Set SQ to YUV converter. */
PVR_SET(PVR_YUV_ADDR, (((unsigned int)texture) & 0xffffff));
// Divide texture width and texture height by 16 and subtract 1.
// The actual values to set are 1, 3, 7, 15, 31, 63.
PVR_SET(PVR_YUV_CFG_1, (((MPEG1_TEXTURE_HEIGHT / 16) - 1) << 8) | ((MPEG1_TEXTURE_WIDTH / 16) - 1));
PVR_GET(PVR_YUV_CFG_1);
/* First frame */
plm_frame_t *frame = plm_decode_video(plm);
float start_time = (float)timer_ms_gettime64() / 1000.0;
float playing_time = 0.0f;
float frame_time = 1.0f / (float)plm_get_framerate(plm);
int decoded = 1;
reset_sound_callback();
/* Init sound stream. */
int samplerate = plm_get_samplerate(plm);
snd_hnd = snd_stream_alloc(sound_callback, 0x10000);
snd_stream_volume(snd_hnd, 0xff);
snd_stream_queue_enable(snd_hnd);
snd_stream_start(snd_hnd, samplerate, 0);
snd_stream_queue_go(snd_hnd);
while (!cancel)
{
/* Check cancel buttons. */
if (buttons)
{
MAPLE_FOREACH_BEGIN(MAPLE_FUNC_CONTROLLER, cont_state_t, st)
if ((st->buttons & buttons) == buttons)
cancel = 1;
MAPLE_FOREACH_END()
}
/* Decode */
playing_time = ((float)timer_ms_gettime64() / 1000.0) - start_time;
if ((frame->time - playing_time) < frame_time)
{
frame = plm_decode_video(plm);
if (!frame)
break;
decoded = 1;
}
snd_stream_poll(snd_hnd);
/* Render */
pvr_wait_ready();
pvr_scene_begin();
if (decoded)
{
app_on_video(plm, frame, 0);
decoded = 0;
}
pvr_list_begin(PVR_LIST_OP_POLY);
display_draw();
pvr_list_finish();
pvr_scene_finish();
}
reset_sound_callback();
plm_destroy(plm);
pvr_mem_free(texture);
snd_stream_destroy(snd_hnd);
return 0;
}
Code: Select all
#include <kos.h>
#include <string.h>
#include <stdio.h>
#include <arch/arch.h>
#include "mpeg1.h"
/* romdisk */
extern uint8 romdisk_boot[];
KOS_INIT_ROMDISK(romdisk_boot);
int main(void)
{
pvr_init_defaults();
snd_stream_init();
Mpeg1Play("/cd/zample.mpg", CONT_START);
//Ian micheal now exits at the end of video
snd_stream_shutdown();
spu_disable(); // Disable the Sound Processing Unit (SPU).
arch_exit(); // Perform system-specific exit operations.
return 0;
}
Before these changes the music would always complete first. Ok still a few places it goes out of sync but much better https://streamable.com/qtn6s4 .. I have done the ring buffer thing before i will see what i can do with that.. Threading did not make it better i tried and it made it crash all the time.. 5 hours wasted!
I will leave your version and not update it till you say so i made a folder with the work today now exits to dcload serial when the video ends it did not before.
https://github.com/ianmicheal/MPEG1-Dec ... updates%5D marked where the changes are in this folder.
Developing a cdrom/gdrom benchmark tool which will show you all speeds of all files on the disc almost done..It benchmarks the disc captures the log to the vmu and can read back with the pvr log viewer with scrolling..
Toolmenu https://streamable.com/5ub9iz
Pvr vmu log viewer https://streamable.com/eb2sp9
Benchmark menu https://streamable.com/lrn7av
It will load the texture of the game benchmark then save to the vmu..
I did this to see speed on a cdr where the best place and names are for media files..There is a very big change depending on how you create and order the files.
-
- DC Developer
- Posts: 48
- Joined: Wed Jan 20, 2016 4:55 am
- Has thanked: 20 times
- Been thanked: 56 times
Re: pl_mpegDC ported running but community help needed
Ian Robinson wrote: ↑Thu Sep 21, 2023 8:47 pm Ok this played my test video and stayed on sync
correct me where i went wrong right now it's the first time it played
the matrix trailer and did not slow downexample.cCode: Select all
#include <kos.h> #define PL_MPEG_IMPLEMENTATION #include "pl_mpeg.h" #include "mpeg1.h" static plm_t *plm; /* textures */ static pvr_ptr_t texture; static int width, height; // Output texture width and height initial values // You can choose from 32, 64, 128, 256, 512, 1024 #define MPEG1_TEXTURE_WIDTH 512 #define MPEG1_TEXTURE_HEIGHT 256 snd_stream_hnd_t snd_hnd; __attribute__((aligned(32))) unsigned int snd_buf[0x10000 / 4]; void display_draw(void) { pvr_poly_cxt_t cxt; pvr_poly_hdr_t hdr; pvr_vertex_t vert; float u = (float)width / (float)MPEG1_TEXTURE_WIDTH; float v = (float)height / (float)MPEG1_TEXTURE_HEIGHT; pvr_poly_cxt_txr(&cxt, PVR_LIST_OP_POLY, PVR_TXRFMT_YUV422 | PVR_TXRFMT_NONTWIDDLED, MPEG1_TEXTURE_WIDTH, MPEG1_TEXTURE_HEIGHT, texture, PVR_FILTER_BILINEAR); pvr_poly_compile(&hdr, &cxt); // hdr.mode3 |= 0x02000000; /* stride */ pvr_prim(&hdr, sizeof(hdr)); vert.argb = PVR_PACK_COLOR(1.0f, 1.0f, 1.0f, 1.0f); vert.oargb = 0; vert.flags = PVR_CMD_VERTEX; vert.x = 1; vert.y = 1; vert.z = 1; vert.u = 0.0f; vert.v = 0.0f; pvr_prim(&vert, sizeof(vert)); vert.x = 640; vert.y = 1; vert.z = 1; vert.u = u; vert.v = 0.0; pvr_prim(&vert, sizeof(vert)); vert.x = 1; vert.y = 480; vert.z = 1; vert.u = 0.0f; vert.v = v; pvr_prim(&vert, sizeof(vert)); vert.x = 640; vert.y = 480; vert.z = 1; vert.u = u; vert.v = v; vert.flags = PVR_CMD_VERTEX_EOL; pvr_prim(&vert, sizeof(vert)); } void app_on_video(plm_t *mpeg, plm_frame_t *frame, void *user) { unsigned int *dest = (unsigned int *)texture; unsigned int *src = (unsigned int *)frame->display; volatile unsigned int *d = (volatile unsigned int *)0xa05f8148; volatile unsigned int *cfg = (volatile unsigned int *)0xa05f814c; volatile unsigned int *stride_reg = (volatile unsigned int *)0xa05f80e4; int stride_value; int stride = 0; int x, y, w, h, i; if (!frame) return; /* set frame size. */ w = frame->width >> 4; h = frame->height >> 4; stride_value = (w >> 1); /* 16 pixel / 2 */ /* Set Stride value. */ *stride_reg &= 0xffffffe0; *stride_reg |= stride_value & 0x01f; /* Set SQ to YUV converter. */ *d = ((unsigned int)dest) & 0xffffff; *cfg = 0x00000f1f; x = *cfg; /* read on once */ for (y = 0; y < h; y++) { for (x = 0; x < w; x++, src += 96) { sq_cpy((void *)0x10800000, (void *)src, 384); } if (!stride) { /* Send dummy mb */ for (i = 0; i < 32 - w; i++) { sq_set((void *)0x10800000, 0, 384); } } } for (i = 0; i < 16 - h; i++) { if (!stride) sq_set((void *)0x10800000, 0, 384 * 32); else sq_set((void *)0x10800000, 0, 384 * w); } } // Define a buffer for audio samples #define AUDIO_SAMPLE_BUFFER_SIZE (1152 * 2 * 10) // Adjust the size as needed // Static variables for sound callback static int mod_start = 0; static int mod_size = 0; static unsigned int audio_sample_buffer[AUDIO_SAMPLE_BUFFER_SIZE]; // Function to reset sound callback's static variables void reset_sound_callback() { mod_start = 0; mod_size = 0; } // Sound callback function void *sound_callback(snd_stream_hnd_t hnd, int size, int *size_out) { unsigned int *dest = audio_sample_buffer; unsigned int *src; int out = 0; src = audio_sample_buffer + mod_start / 4; for (int i = 0; i < mod_size / 4; i++) *dest++ = *src++; out += mod_size; while (size > out) { plm_samples_t *sample = plm_decode_audio(plm); if (sample == NULL) { reset_sound_callback(); // Reset static variables when audio ends break; } src = (unsigned int *)sample->pcm; for (int i = 0; i < 1152 / 2; i++) *dest++ = *src++; out += 1152 * 2; } mod_start = size; mod_size = out - size; *size_out = size; return (void *)audio_sample_buffer; } int Mpeg1Play(const char *filename, unsigned int buttons) { int cancel = 0; plm = plm_create_with_filename(filename); if (!plm) return -1; texture = pvr_mem_malloc(512 * 256 * 2); width = plm_get_width(plm); height = plm_get_height(plm); /* Set SQ to YUV converter. */ PVR_SET(PVR_YUV_ADDR, (((unsigned int)texture) & 0xffffff)); // Divide texture width and texture height by 16 and subtract 1. // The actual values to set are 1, 3, 7, 15, 31, 63. PVR_SET(PVR_YUV_CFG_1, (((MPEG1_TEXTURE_HEIGHT / 16) - 1) << 8) | ((MPEG1_TEXTURE_WIDTH / 16) - 1)); PVR_GET(PVR_YUV_CFG_1); /* First frame */ plm_frame_t *frame = plm_decode_video(plm); float start_time = (float)timer_ms_gettime64() / 1000.0; float playing_time = 0.0f; float frame_time = 1.0f / (float)plm_get_framerate(plm); int decoded = 1; reset_sound_callback(); /* Init sound stream. */ int samplerate = plm_get_samplerate(plm); snd_hnd = snd_stream_alloc(sound_callback, 0x10000); snd_stream_volume(snd_hnd, 0xff); snd_stream_queue_enable(snd_hnd); snd_stream_start(snd_hnd, samplerate, 0); snd_stream_queue_go(snd_hnd); while (!cancel) { /* Check cancel buttons. */ if (buttons) { MAPLE_FOREACH_BEGIN(MAPLE_FUNC_CONTROLLER, cont_state_t, st) if ((st->buttons & buttons) == buttons) cancel = 1; MAPLE_FOREACH_END() } /* Decode */ playing_time = ((float)timer_ms_gettime64() / 1000.0) - start_time; if ((frame->time - playing_time) < frame_time) { frame = plm_decode_video(plm); if (!frame) break; decoded = 1; } snd_stream_poll(snd_hnd); /* Render */ pvr_wait_ready(); pvr_scene_begin(); if (decoded) { app_on_video(plm, frame, 0); decoded = 0; } pvr_list_begin(PVR_LIST_OP_POLY); display_draw(); pvr_list_finish(); pvr_scene_finish(); } reset_sound_callback(); plm_destroy(plm); pvr_mem_free(texture); snd_stream_destroy(snd_hnd); return 0; }
Names starting with Z are the fastest when dummied.Code: Select all
#include <kos.h> #include <string.h> #include <stdio.h> #include <arch/arch.h> #include "mpeg1.h" /* romdisk */ extern uint8 romdisk_boot[]; KOS_INIT_ROMDISK(romdisk_boot); int main(void) { pvr_init_defaults(); snd_stream_init(); Mpeg1Play("/cd/zample.mpg", CONT_START); //Ian micheal now exits at the end of video snd_stream_shutdown(); spu_disable(); // Disable the Sound Processing Unit (SPU). arch_exit(); // Perform system-specific exit operations. return 0; }
Before these changes the music would always complete first. Ok still a few places it goes out of sync but much better https://streamable.com/qtn6s4 .. I have done the ring buffer thing before i will see what i can do with that.. Threading did not make it better i tried and it made it crash all the time.. 5 hours wasted!
I will leave your version and not update it till you say so i made a folder with the work today now exits to dcload serial when the video ends it did not before.
https://github.com/ianmicheal/MPEG1-Dec ... updates%5D marked where the changes are in this folder.
Developing a cdrom/gdrom benchmark tool which will show you all speeds of all files on the disc almost done..It benchmarks the disc captures the log to the vmu and can read back with the pvr log viewer with scrolling..
Toolmenu https://streamable.com/5ub9iz
Pvr vmu log viewer https://streamable.com/eb2sp9
Benchmark menu https://streamable.com/lrn7av
It will load the texture of the game benchmark then save to the vmu..
I did this to see speed on a cdr where the best place and names are for media files..There is a very big change depending on how you create and order the files.
I think it's very good! Are you not using the snd_buf array anymore?
I also saw the Matrix trailer. Ah, so nostalgic. It's definitely slowing down. From what I've seen, it looks like the processing can't keep up where scenes are rapidly changing.
Should I skip frames when a delay occurs? I think it is the file reading that is slow, so perhaps there is room to improve the file reading functions (plm_buffer etc.) in the future. It would be great if I could use something like GDDMA...
Your 5 hours were for us. thank you!
If it is updated, could I also ask for changes to the cancel button processing in mpeg.c?
Code: Select all
/* Check cancel buttons. */
MAPLE_FOREACH_BEGIN(MAPLE_FUNC_CONTROLLER, cont_state_t, st)
if (buttons && ((st->buttons & buttons) == buttons))
cancel = 1; /* Push cancel buttons */
if (st->buttons == 0x60e)
cancel = 2; /* ABXY + START (Software reset) */
MAPLE_FOREACH_END()
...
...
return cancel;
However, it is surprising that there is such a difference in disk reading speed. Your tools are very interesting.
- These users thanked the author Twada for the post (total 2):
- Ian Robinson • GyroVorbis
- Ian Robinson
- DC Developer
- Posts: 126
- Joined: Mon Mar 11, 2019 7:12 am
- Has thanked: 225 times
- Been thanked: 45 times
Re: pl_mpegDC ported running but community help needed
Implemented a ringbuffer version
working about the same but slightly better
https://github.com/ianmicheal/MPEG1-Dec ... ngbuffer.c
Code: Select all
#include <kos.h>
#define PL_MPEG_IMPLEMENTATION
#include "pl_mpeg.h"
#include "mpeg1.h"
static plm_t *plm;
/* textures */
static pvr_ptr_t texture;
static int width, height;
// Output texture width and height initial values
// You can choose from 32, 64, 128, 256, 512, 1024
#define MPEG1_TEXTURE_WIDTH 512
#define MPEG1_TEXTURE_HEIGHT 256
snd_stream_hnd_t snd_hnd;
__attribute__((aligned(32))) unsigned int snd_buf[0x10000 / 4];
// Structure to represent a video frame
typedef struct {
plm_frame_t *frame;
} VideoFrame;
//Ian micheal Implemented a ringbuffer version
// Ring buffer to hold video frames
#define RING_BUFFER_SIZE 10
static VideoFrame ringBuffer[RING_BUFFER_SIZE];
static int ringBufferHead = 0;
static int ringBufferTail = 0;
// Function to initialize the ring buffer
void initRingBuffer() {
ringBufferHead = 0;
ringBufferTail = 0;
memset(ringBuffer, 0, sizeof(ringBuffer));
}
// Function to enqueue a video frame into the ring buffer
void enqueueFrame(plm_frame_t *frame) {
if ((ringBufferHead + 1) % RING_BUFFER_SIZE != ringBufferTail) {
ringBuffer[ringBufferHead].frame = frame;
ringBufferHead = (ringBufferHead + 1) % RING_BUFFER_SIZE;
}
}
// Function to dequeue a video frame from the ring buffer
plm_frame_t *dequeueFrame() {
plm_frame_t *frame = NULL;
if (ringBufferHead != ringBufferTail) {
frame = ringBuffer[ringBufferTail].frame;
ringBufferTail = (ringBufferTail + 1) % RING_BUFFER_SIZE;
}
return frame;
}
void display_draw(void)
{
pvr_poly_cxt_t cxt;
pvr_poly_hdr_t hdr;
pvr_vertex_t vert;
float u = (float)width / (float)MPEG1_TEXTURE_WIDTH;
float v = (float)height / (float)MPEG1_TEXTURE_HEIGHT;
pvr_poly_cxt_txr(&cxt, PVR_LIST_OP_POLY, PVR_TXRFMT_YUV422 | PVR_TXRFMT_NONTWIDDLED, MPEG1_TEXTURE_WIDTH, MPEG1_TEXTURE_HEIGHT, texture, PVR_FILTER_BILINEAR);
pvr_poly_compile(&hdr, &cxt);
// hdr.mode3 |= 0x02000000; /* stride */
pvr_prim(&hdr, sizeof(hdr));
vert.argb = PVR_PACK_COLOR(1.0f, 1.0f, 1.0f, 1.0f);
vert.oargb = 0;
vert.flags = PVR_CMD_VERTEX;
vert.x = 1;
vert.y = 1;
vert.z = 1;
vert.u = 0.0f;
vert.v = 0.0f;
pvr_prim(&vert, sizeof(vert));
vert.x = 640;
vert.y = 1;
vert.z = 1;
vert.u = u;
vert.v = 0.0;
pvr_prim(&vert, sizeof(vert));
vert.x = 1;
vert.y = 480;
vert.z = 1;
vert.u = 0.0f;
vert.v = v;
pvr_prim(&vert, sizeof(vert));
vert.x = 640;
vert.y = 480;
vert.z = 1;
vert.u = u;
vert.v = v;
vert.flags = PVR_CMD_VERTEX_EOL;
pvr_prim(&vert, sizeof(vert));
}
void app_on_video(plm_t *mpeg, plm_frame_t *frame, void *user)
{
unsigned int *dest = (unsigned int *)texture;
unsigned int *src = (unsigned int *)frame->display;
volatile unsigned int *d = (volatile unsigned int *)0xa05f8148;
volatile unsigned int *cfg = (volatile unsigned int *)0xa05f814c;
volatile unsigned int *stride_reg = (volatile unsigned int *)0xa05f80e4;
int stride_value;
int stride = 0;
int x, y, w, h, i;
if (!frame)
return;
/* set frame size. */
w = frame->width >> 4;
h = frame->height >> 4;
stride_value = (w >> 1); /* 16 pixel / 2 */
/* Set Stride value. */
*stride_reg &= 0xffffffe0;
*stride_reg |= stride_value & 0x01f;
/* Set SQ to YUV converter. */
*d = ((unsigned int)dest) & 0xffffff;
*cfg = 0x00000f1f;
x = *cfg; /* read on once */
for (y = 0; y < h; y++)
{
for (x = 0; x < w; x++, src += 96)
{
sq_cpy((void *)0x10800000, (void *)src, 384);
}
if (!stride)
{
/* Send dummy mb */
for (i = 0; i < 32 - w; i++)
{
sq_set((void *)0x10800000, 0, 384);
}
}
}
for (i = 0; i < 16 - h; i++)
{
if (!stride)
sq_set((void *)0x10800000, 0, 384 * 32);
else
sq_set((void *)0x10800000, 0, 384 * w);
}
}
// Define a buffer for audio samples
#define AUDIO_SAMPLE_BUFFER_SIZE (1152 * 2 * 10) // Adjust the size as needed
// Static variables for sound callback
static int mod_start = 0;
static int mod_size = 0;
static unsigned int audio_sample_buffer[AUDIO_SAMPLE_BUFFER_SIZE];
//Ian micheal added call back sound reset and buffer
// Function to reset sound callback's static variables
void reset_sound_callback()
{
mod_start = 0;
mod_size = 0;
}
// Sound callback function
void *sound_callback(snd_stream_hnd_t hnd, int size, int *size_out)
{
unsigned int *dest = audio_sample_buffer;
unsigned int *src;
int out = 0;
src = audio_sample_buffer + mod_start / 4;
for (int i = 0; i < mod_size / 4; i++)
*dest++ = *src++;
out += mod_size;
while (size > out)
{
plm_samples_t *sample = plm_decode_audio(plm);
if (sample == NULL)
{
reset_sound_callback(); // Reset static variables when audio ends
break;
}
src = (unsigned int *)sample->pcm;
for (int i = 0; i < 1152 / 2; i++)
*dest++ = *src++;
out += 1152 * 2;
}
mod_start = size;
mod_size = out - size;
*size_out = size;
return (void *)audio_sample_buffer;
}
int Mpeg1Play(const char *filename, unsigned int buttons)
{
int cancel = 0;
plm = plm_create_with_filename(filename);
if (!plm)
return -1;
texture = pvr_mem_malloc(512 * 256 * 2);
width = plm_get_width(plm);
height = plm_get_height(plm);
// Initialize the ring buffer
initRingBuffer();
/* Set SQ to YUV converter. */
PVR_SET(PVR_YUV_ADDR, (((unsigned int)texture) & 0xffffff));
// Divide texture width and texture height by 16 and subtract 1.
// The actual values to set are 1, 3, 7, 15, 31, 63.
PVR_SET(PVR_YUV_CFG_1, (((MPEG1_TEXTURE_HEIGHT / 16) - 1) << 8) | ((MPEG1_TEXTURE_WIDTH / 16) - 1));
PVR_GET(PVR_YUV_CFG_1);
/* First frame */
plm_frame_t *frame = plm_decode_video(plm);
float start_time = (float)timer_ms_gettime64() / 1000.0;
float playing_time = 0.0f;
float frame_time = 1.0f / (float)plm_get_framerate(plm);
int decoded = 1;
//Ian micheal added call back sound reset and buffer
reset_sound_callback();
/* Init sound stream. */
int samplerate = plm_get_samplerate(plm);
snd_hnd = snd_stream_alloc(sound_callback, 0x10000);
snd_stream_volume(snd_hnd, 0xff);
snd_stream_queue_enable(snd_hnd);
snd_stream_start(snd_hnd, samplerate, 0);
snd_stream_queue_go(snd_hnd);
while (!cancel)
{
/* Check cancel buttons. */
if (buttons)
{
MAPLE_FOREACH_BEGIN(MAPLE_FUNC_CONTROLLER, cont_state_t, st)
if ((st->buttons & buttons) == buttons)
cancel = 1;
MAPLE_FOREACH_END()
}
/* Decode */
playing_time = ((float)timer_ms_gettime64() / 1000.0) - start_time;
if ((frame->time - playing_time) < frame_time)
{
frame = plm_decode_video(plm);
if (!frame)
break;
decoded = 1;
// Enqueue the frame into the ring buffer
enqueueFrame(frame);
}
snd_stream_poll(snd_hnd);
/* Render */
pvr_wait_ready();
pvr_scene_begin();
if (decoded)
{
frame = dequeueFrame();
if (frame) {
app_on_video(plm, frame, 0);
}
decoded = 0;
}
pvr_list_begin(PVR_LIST_OP_POLY);
display_draw();
pvr_list_finish();
pvr_scene_finish();
}
//Ian micheal added call back sound reset and buffer
reset_sound_callback();
plm_destroy(plm);
pvr_mem_free(texture);
snd_stream_destroy(snd_hnd);
return 0;
}
https://github.com/ianmicheal/MPEG1-Dec ... ngbuffer.c
-
- DC Developer
- Posts: 48
- Joined: Wed Jan 20, 2016 4:55 am
- Has thanked: 20 times
- Been thanked: 56 times
Re: pl_mpegDC ported running but community help needed
Oh, cool ring buffer!Ian Robinson wrote: ↑Fri Sep 22, 2023 5:10 pm Implemented a ringbuffer versionworking about the same but slightly betterCode: Select all
#include <kos.h> #define PL_MPEG_IMPLEMENTATION #include "pl_mpeg.h" #include "mpeg1.h" static plm_t *plm; /* textures */ static pvr_ptr_t texture; static int width, height; // Output texture width and height initial values // You can choose from 32, 64, 128, 256, 512, 1024 #define MPEG1_TEXTURE_WIDTH 512 #define MPEG1_TEXTURE_HEIGHT 256 snd_stream_hnd_t snd_hnd; __attribute__((aligned(32))) unsigned int snd_buf[0x10000 / 4]; // Structure to represent a video frame typedef struct { plm_frame_t *frame; } VideoFrame; //Ian micheal Implemented a ringbuffer version // Ring buffer to hold video frames #define RING_BUFFER_SIZE 10 static VideoFrame ringBuffer[RING_BUFFER_SIZE]; static int ringBufferHead = 0; static int ringBufferTail = 0; // Function to initialize the ring buffer void initRingBuffer() { ringBufferHead = 0; ringBufferTail = 0; memset(ringBuffer, 0, sizeof(ringBuffer)); } // Function to enqueue a video frame into the ring buffer void enqueueFrame(plm_frame_t *frame) { if ((ringBufferHead + 1) % RING_BUFFER_SIZE != ringBufferTail) { ringBuffer[ringBufferHead].frame = frame; ringBufferHead = (ringBufferHead + 1) % RING_BUFFER_SIZE; } } // Function to dequeue a video frame from the ring buffer plm_frame_t *dequeueFrame() { plm_frame_t *frame = NULL; if (ringBufferHead != ringBufferTail) { frame = ringBuffer[ringBufferTail].frame; ringBufferTail = (ringBufferTail + 1) % RING_BUFFER_SIZE; } return frame; } void display_draw(void) { pvr_poly_cxt_t cxt; pvr_poly_hdr_t hdr; pvr_vertex_t vert; float u = (float)width / (float)MPEG1_TEXTURE_WIDTH; float v = (float)height / (float)MPEG1_TEXTURE_HEIGHT; pvr_poly_cxt_txr(&cxt, PVR_LIST_OP_POLY, PVR_TXRFMT_YUV422 | PVR_TXRFMT_NONTWIDDLED, MPEG1_TEXTURE_WIDTH, MPEG1_TEXTURE_HEIGHT, texture, PVR_FILTER_BILINEAR); pvr_poly_compile(&hdr, &cxt); // hdr.mode3 |= 0x02000000; /* stride */ pvr_prim(&hdr, sizeof(hdr)); vert.argb = PVR_PACK_COLOR(1.0f, 1.0f, 1.0f, 1.0f); vert.oargb = 0; vert.flags = PVR_CMD_VERTEX; vert.x = 1; vert.y = 1; vert.z = 1; vert.u = 0.0f; vert.v = 0.0f; pvr_prim(&vert, sizeof(vert)); vert.x = 640; vert.y = 1; vert.z = 1; vert.u = u; vert.v = 0.0; pvr_prim(&vert, sizeof(vert)); vert.x = 1; vert.y = 480; vert.z = 1; vert.u = 0.0f; vert.v = v; pvr_prim(&vert, sizeof(vert)); vert.x = 640; vert.y = 480; vert.z = 1; vert.u = u; vert.v = v; vert.flags = PVR_CMD_VERTEX_EOL; pvr_prim(&vert, sizeof(vert)); } void app_on_video(plm_t *mpeg, plm_frame_t *frame, void *user) { unsigned int *dest = (unsigned int *)texture; unsigned int *src = (unsigned int *)frame->display; volatile unsigned int *d = (volatile unsigned int *)0xa05f8148; volatile unsigned int *cfg = (volatile unsigned int *)0xa05f814c; volatile unsigned int *stride_reg = (volatile unsigned int *)0xa05f80e4; int stride_value; int stride = 0; int x, y, w, h, i; if (!frame) return; /* set frame size. */ w = frame->width >> 4; h = frame->height >> 4; stride_value = (w >> 1); /* 16 pixel / 2 */ /* Set Stride value. */ *stride_reg &= 0xffffffe0; *stride_reg |= stride_value & 0x01f; /* Set SQ to YUV converter. */ *d = ((unsigned int)dest) & 0xffffff; *cfg = 0x00000f1f; x = *cfg; /* read on once */ for (y = 0; y < h; y++) { for (x = 0; x < w; x++, src += 96) { sq_cpy((void *)0x10800000, (void *)src, 384); } if (!stride) { /* Send dummy mb */ for (i = 0; i < 32 - w; i++) { sq_set((void *)0x10800000, 0, 384); } } } for (i = 0; i < 16 - h; i++) { if (!stride) sq_set((void *)0x10800000, 0, 384 * 32); else sq_set((void *)0x10800000, 0, 384 * w); } } // Define a buffer for audio samples #define AUDIO_SAMPLE_BUFFER_SIZE (1152 * 2 * 10) // Adjust the size as needed // Static variables for sound callback static int mod_start = 0; static int mod_size = 0; static unsigned int audio_sample_buffer[AUDIO_SAMPLE_BUFFER_SIZE]; //Ian micheal added call back sound reset and buffer // Function to reset sound callback's static variables void reset_sound_callback() { mod_start = 0; mod_size = 0; } // Sound callback function void *sound_callback(snd_stream_hnd_t hnd, int size, int *size_out) { unsigned int *dest = audio_sample_buffer; unsigned int *src; int out = 0; src = audio_sample_buffer + mod_start / 4; for (int i = 0; i < mod_size / 4; i++) *dest++ = *src++; out += mod_size; while (size > out) { plm_samples_t *sample = plm_decode_audio(plm); if (sample == NULL) { reset_sound_callback(); // Reset static variables when audio ends break; } src = (unsigned int *)sample->pcm; for (int i = 0; i < 1152 / 2; i++) *dest++ = *src++; out += 1152 * 2; } mod_start = size; mod_size = out - size; *size_out = size; return (void *)audio_sample_buffer; } int Mpeg1Play(const char *filename, unsigned int buttons) { int cancel = 0; plm = plm_create_with_filename(filename); if (!plm) return -1; texture = pvr_mem_malloc(512 * 256 * 2); width = plm_get_width(plm); height = plm_get_height(plm); // Initialize the ring buffer initRingBuffer(); /* Set SQ to YUV converter. */ PVR_SET(PVR_YUV_ADDR, (((unsigned int)texture) & 0xffffff)); // Divide texture width and texture height by 16 and subtract 1. // The actual values to set are 1, 3, 7, 15, 31, 63. PVR_SET(PVR_YUV_CFG_1, (((MPEG1_TEXTURE_HEIGHT / 16) - 1) << 8) | ((MPEG1_TEXTURE_WIDTH / 16) - 1)); PVR_GET(PVR_YUV_CFG_1); /* First frame */ plm_frame_t *frame = plm_decode_video(plm); float start_time = (float)timer_ms_gettime64() / 1000.0; float playing_time = 0.0f; float frame_time = 1.0f / (float)plm_get_framerate(plm); int decoded = 1; //Ian micheal added call back sound reset and buffer reset_sound_callback(); /* Init sound stream. */ int samplerate = plm_get_samplerate(plm); snd_hnd = snd_stream_alloc(sound_callback, 0x10000); snd_stream_volume(snd_hnd, 0xff); snd_stream_queue_enable(snd_hnd); snd_stream_start(snd_hnd, samplerate, 0); snd_stream_queue_go(snd_hnd); while (!cancel) { /* Check cancel buttons. */ if (buttons) { MAPLE_FOREACH_BEGIN(MAPLE_FUNC_CONTROLLER, cont_state_t, st) if ((st->buttons & buttons) == buttons) cancel = 1; MAPLE_FOREACH_END() } /* Decode */ playing_time = ((float)timer_ms_gettime64() / 1000.0) - start_time; if ((frame->time - playing_time) < frame_time) { frame = plm_decode_video(plm); if (!frame) break; decoded = 1; // Enqueue the frame into the ring buffer enqueueFrame(frame); } snd_stream_poll(snd_hnd); /* Render */ pvr_wait_ready(); pvr_scene_begin(); if (decoded) { frame = dequeueFrame(); if (frame) { app_on_video(plm, frame, 0); } decoded = 0; } pvr_list_begin(PVR_LIST_OP_POLY); display_draw(); pvr_list_finish(); pvr_scene_finish(); } //Ian micheal added call back sound reset and buffer reset_sound_callback(); plm_destroy(plm); pvr_mem_free(texture); snd_stream_destroy(snd_hnd); return 0; }
https://github.com/ianmicheal/MPEG1-Dec ... ngbuffer.c
However, pl_mpeg only has a three frame buffer internally.
forward, backward, and current. pl_mpeg uses these three buffers interchangeably.
This order is the reference order, not the playback order. B frames are not referenced, so they never go forward and backward.
Therefore, if you hold a pointer in a ring buffer, the contents will be overwritten.
When implementing a ring buffer, I think you have to create a new buffer and copy its contents.
- These users thanked the author Twada for the post:
- Ian Robinson
- Ian Robinson
- DC Developer
- Posts: 126
- Joined: Mon Mar 11, 2019 7:12 am
- Has thanked: 225 times
- Been thanked: 45 times
Re: pl_mpegDC ported running but community help needed
Right i was just trying it out crazy it seem to help..Twada wrote: ↑Fri Sep 22, 2023 6:04 pmOh, cool ring buffer!Ian Robinson wrote: ↑Fri Sep 22, 2023 5:10 pm Implemented a ringbuffer versionworking about the same but slightly betterCode: Select all
#include <kos.h> #define PL_MPEG_IMPLEMENTATION #include "pl_mpeg.h" #include "mpeg1.h" static plm_t *plm; /* textures */ static pvr_ptr_t texture; static int width, height; // Output texture width and height initial values // You can choose from 32, 64, 128, 256, 512, 1024 #define MPEG1_TEXTURE_WIDTH 512 #define MPEG1_TEXTURE_HEIGHT 256 snd_stream_hnd_t snd_hnd; __attribute__((aligned(32))) unsigned int snd_buf[0x10000 / 4]; // Structure to represent a video frame typedef struct { plm_frame_t *frame; } VideoFrame; //Ian micheal Implemented a ringbuffer version // Ring buffer to hold video frames #define RING_BUFFER_SIZE 10 static VideoFrame ringBuffer[RING_BUFFER_SIZE]; static int ringBufferHead = 0; static int ringBufferTail = 0; // Function to initialize the ring buffer void initRingBuffer() { ringBufferHead = 0; ringBufferTail = 0; memset(ringBuffer, 0, sizeof(ringBuffer)); } // Function to enqueue a video frame into the ring buffer void enqueueFrame(plm_frame_t *frame) { if ((ringBufferHead + 1) % RING_BUFFER_SIZE != ringBufferTail) { ringBuffer[ringBufferHead].frame = frame; ringBufferHead = (ringBufferHead + 1) % RING_BUFFER_SIZE; } } // Function to dequeue a video frame from the ring buffer plm_frame_t *dequeueFrame() { plm_frame_t *frame = NULL; if (ringBufferHead != ringBufferTail) { frame = ringBuffer[ringBufferTail].frame; ringBufferTail = (ringBufferTail + 1) % RING_BUFFER_SIZE; } return frame; } void display_draw(void) { pvr_poly_cxt_t cxt; pvr_poly_hdr_t hdr; pvr_vertex_t vert; float u = (float)width / (float)MPEG1_TEXTURE_WIDTH; float v = (float)height / (float)MPEG1_TEXTURE_HEIGHT; pvr_poly_cxt_txr(&cxt, PVR_LIST_OP_POLY, PVR_TXRFMT_YUV422 | PVR_TXRFMT_NONTWIDDLED, MPEG1_TEXTURE_WIDTH, MPEG1_TEXTURE_HEIGHT, texture, PVR_FILTER_BILINEAR); pvr_poly_compile(&hdr, &cxt); // hdr.mode3 |= 0x02000000; /* stride */ pvr_prim(&hdr, sizeof(hdr)); vert.argb = PVR_PACK_COLOR(1.0f, 1.0f, 1.0f, 1.0f); vert.oargb = 0; vert.flags = PVR_CMD_VERTEX; vert.x = 1; vert.y = 1; vert.z = 1; vert.u = 0.0f; vert.v = 0.0f; pvr_prim(&vert, sizeof(vert)); vert.x = 640; vert.y = 1; vert.z = 1; vert.u = u; vert.v = 0.0; pvr_prim(&vert, sizeof(vert)); vert.x = 1; vert.y = 480; vert.z = 1; vert.u = 0.0f; vert.v = v; pvr_prim(&vert, sizeof(vert)); vert.x = 640; vert.y = 480; vert.z = 1; vert.u = u; vert.v = v; vert.flags = PVR_CMD_VERTEX_EOL; pvr_prim(&vert, sizeof(vert)); } void app_on_video(plm_t *mpeg, plm_frame_t *frame, void *user) { unsigned int *dest = (unsigned int *)texture; unsigned int *src = (unsigned int *)frame->display; volatile unsigned int *d = (volatile unsigned int *)0xa05f8148; volatile unsigned int *cfg = (volatile unsigned int *)0xa05f814c; volatile unsigned int *stride_reg = (volatile unsigned int *)0xa05f80e4; int stride_value; int stride = 0; int x, y, w, h, i; if (!frame) return; /* set frame size. */ w = frame->width >> 4; h = frame->height >> 4; stride_value = (w >> 1); /* 16 pixel / 2 */ /* Set Stride value. */ *stride_reg &= 0xffffffe0; *stride_reg |= stride_value & 0x01f; /* Set SQ to YUV converter. */ *d = ((unsigned int)dest) & 0xffffff; *cfg = 0x00000f1f; x = *cfg; /* read on once */ for (y = 0; y < h; y++) { for (x = 0; x < w; x++, src += 96) { sq_cpy((void *)0x10800000, (void *)src, 384); } if (!stride) { /* Send dummy mb */ for (i = 0; i < 32 - w; i++) { sq_set((void *)0x10800000, 0, 384); } } } for (i = 0; i < 16 - h; i++) { if (!stride) sq_set((void *)0x10800000, 0, 384 * 32); else sq_set((void *)0x10800000, 0, 384 * w); } } // Define a buffer for audio samples #define AUDIO_SAMPLE_BUFFER_SIZE (1152 * 2 * 10) // Adjust the size as needed // Static variables for sound callback static int mod_start = 0; static int mod_size = 0; static unsigned int audio_sample_buffer[AUDIO_SAMPLE_BUFFER_SIZE]; //Ian micheal added call back sound reset and buffer // Function to reset sound callback's static variables void reset_sound_callback() { mod_start = 0; mod_size = 0; } // Sound callback function void *sound_callback(snd_stream_hnd_t hnd, int size, int *size_out) { unsigned int *dest = audio_sample_buffer; unsigned int *src; int out = 0; src = audio_sample_buffer + mod_start / 4; for (int i = 0; i < mod_size / 4; i++) *dest++ = *src++; out += mod_size; while (size > out) { plm_samples_t *sample = plm_decode_audio(plm); if (sample == NULL) { reset_sound_callback(); // Reset static variables when audio ends break; } src = (unsigned int *)sample->pcm; for (int i = 0; i < 1152 / 2; i++) *dest++ = *src++; out += 1152 * 2; } mod_start = size; mod_size = out - size; *size_out = size; return (void *)audio_sample_buffer; } int Mpeg1Play(const char *filename, unsigned int buttons) { int cancel = 0; plm = plm_create_with_filename(filename); if (!plm) return -1; texture = pvr_mem_malloc(512 * 256 * 2); width = plm_get_width(plm); height = plm_get_height(plm); // Initialize the ring buffer initRingBuffer(); /* Set SQ to YUV converter. */ PVR_SET(PVR_YUV_ADDR, (((unsigned int)texture) & 0xffffff)); // Divide texture width and texture height by 16 and subtract 1. // The actual values to set are 1, 3, 7, 15, 31, 63. PVR_SET(PVR_YUV_CFG_1, (((MPEG1_TEXTURE_HEIGHT / 16) - 1) << 8) | ((MPEG1_TEXTURE_WIDTH / 16) - 1)); PVR_GET(PVR_YUV_CFG_1); /* First frame */ plm_frame_t *frame = plm_decode_video(plm); float start_time = (float)timer_ms_gettime64() / 1000.0; float playing_time = 0.0f; float frame_time = 1.0f / (float)plm_get_framerate(plm); int decoded = 1; //Ian micheal added call back sound reset and buffer reset_sound_callback(); /* Init sound stream. */ int samplerate = plm_get_samplerate(plm); snd_hnd = snd_stream_alloc(sound_callback, 0x10000); snd_stream_volume(snd_hnd, 0xff); snd_stream_queue_enable(snd_hnd); snd_stream_start(snd_hnd, samplerate, 0); snd_stream_queue_go(snd_hnd); while (!cancel) { /* Check cancel buttons. */ if (buttons) { MAPLE_FOREACH_BEGIN(MAPLE_FUNC_CONTROLLER, cont_state_t, st) if ((st->buttons & buttons) == buttons) cancel = 1; MAPLE_FOREACH_END() } /* Decode */ playing_time = ((float)timer_ms_gettime64() / 1000.0) - start_time; if ((frame->time - playing_time) < frame_time) { frame = plm_decode_video(plm); if (!frame) break; decoded = 1; // Enqueue the frame into the ring buffer enqueueFrame(frame); } snd_stream_poll(snd_hnd); /* Render */ pvr_wait_ready(); pvr_scene_begin(); if (decoded) { frame = dequeueFrame(); if (frame) { app_on_video(plm, frame, 0); } decoded = 0; } pvr_list_begin(PVR_LIST_OP_POLY); display_draw(); pvr_list_finish(); pvr_scene_finish(); } //Ian micheal added call back sound reset and buffer reset_sound_callback(); plm_destroy(plm); pvr_mem_free(texture); snd_stream_destroy(snd_hnd); return 0; }
https://github.com/ianmicheal/MPEG1-Dec ... ngbuffer.c
However, pl_mpeg only has a three frame buffer internally.
forward, backward, and current. pl_mpeg uses these three buffers interchangeably.
This order is the reference order, not the playback order. B frames are not referenced, so they never go forward and backward.
Therefore, if you hold a pointer in a ring buffer, the contents will be overwritten.
When implementing a ring buffer, I think you have to create a new buffer and copy its contents.
- These users thanked the author Ian Robinson for the post:
- GyroVorbis
- Ian Robinson
- DC Developer
- Posts: 126
- Joined: Mon Mar 11, 2019 7:12 am
- Has thanked: 225 times
- Been thanked: 45 times
Re: pl_mpegDC ported running but community help needed
Implemented correct texture scaling
example fixed
Before squashed
Code: Select all
#define UV_EPSILON 0.100f
#define screenWidth 640
#define screenHeight 480
void display_draw(void)
{
pvr_poly_cxt_t cxt;
pvr_poly_hdr_t hdr;
pvr_vertex_t vert;
float u = (float)width / (float)MPEG1_TEXTURE_WIDTH;
float v = (float)height / (float)MPEG1_TEXTURE_HEIGHT;
pvr_poly_cxt_txr(&cxt, PVR_LIST_OP_POLY, PVR_TXRFMT_YUV422 | PVR_TXRFMT_NONTWIDDLED, MPEG1_TEXTURE_WIDTH, MPEG1_TEXTURE_HEIGHT, texture, PVR_FILTER_BILINEAR);
pvr_poly_compile(&hdr, &cxt);
// hdr.mode3 |= 0x02000000; /* stride */
pvr_prim(&hdr, sizeof(hdr));
vert.argb = PVR_PACK_COLOR(1.0f, 1.0f, 1.0f, 1.0f);
vert.oargb = 0;
vert.flags = PVR_CMD_VERTEX;
vert.x = 1;
vert.y = 1;
vert.z = 1;
vert.u = UV_EPSILON;
vert.v = UV_EPSILON;
pvr_prim(&vert, sizeof(vert));
vert.x = screenWidth;
vert.y = 1;
vert.z = 1;
vert.u = u - UV_EPSILON;
vert.v = UV_EPSILON;
pvr_prim(&vert, sizeof(vert));
vert.x = 1;
vert.y = screenHeight;
vert.z = 1;
vert.u = UV_EPSILON;
vert.v = v - UV_EPSILON;
pvr_prim(&vert, sizeof(vert));
vert.x = screenWidth;
vert.y = screenHeight;
vert.z = 1;
vert.u = u - UV_EPSILON;
vert.v = v - UV_EPSILON;
vert.flags = PVR_CMD_VERTEX_EOL;
pvr_prim(&vert, sizeof(vert));
}
- These users thanked the author Ian Robinson for the post (total 2):
- Twada • GyroVorbis
- Ian Robinson
- DC Developer
- Posts: 126
- Joined: Mon Mar 11, 2019 7:12 am
- Has thanked: 225 times
- Been thanked: 45 times
Re: pl_mpegDC ported running but community help needed
Well i did more profiling and testing found it stays perfect on sync with these settings
https://streamable.com/wo7d47 Example video 2
https://streamable.com/dd5v3s Example 3 HQ
https://streamable.com/ygtjjh Updated texture scale now shows the whole screen both sizes in frame..
Other things in this update just throwing things at the wall..
Using 64bit SQ code i have does not make any change i dont think
does not break anything ether.
For movies on sync on ffmpeg i used
I found xilisoft to make better looking at the same bitrate but it was set for cbr so more like this this above is for 24fps best quality so far and on sync
Example video of HQ again OLE tv demo lol
https://streamable.com/35gj9y
Example video 1https://streamable.com/wo7d47 Example video 2
https://streamable.com/dd5v3s Example 3 HQ
https://streamable.com/ygtjjh Updated texture scale now shows the whole screen both sizes in frame..
Other things in this update just throwing things at the wall..
Using 64bit SQ code i have does not make any change i dont think
does not break anything ether.
Code: Select all
#include <kos.h>
#define PL_MPEG_IMPLEMENTATION
#include "pl_mpeg.h"
#include "mpeg1.h"
static plm_t *plm;
/* textures */
static pvr_ptr_t texture;
static int width, height;
// Output texture width and height initial values
// You can choose from 32, 64, 128, 256, 512, 1024
#define MPEG1_TEXTURE_WIDTH 512
#define MPEG1_TEXTURE_HEIGHT 256
snd_stream_hnd_t snd_hnd;
__attribute__((aligned(32))) unsigned int snd_buf[0x10000 / 4];
// Structure to represent a video frame
typedef struct {
plm_frame_t *frame;
} VideoFrame;
//Ian micheal Implemented a ringbuffer version
// Ring buffer to hold video frames
#define RING_BUFFER_SIZE 20
static VideoFrame ringBuffer[RING_BUFFER_SIZE];
static int ringBufferHead = 0;
static int ringBufferTail = 0;
// Function to initialize the ring buffer
void initRingBuffer() {
ringBufferHead = 0;
ringBufferTail = 0;
memset(ringBuffer, 0, sizeof(ringBuffer));
}
// Function to enqueue a video frame into the ring buffer
void enqueueFrame(plm_frame_t *frame) {
if ((ringBufferHead + 1) % RING_BUFFER_SIZE != ringBufferTail) {
ringBuffer[ringBufferHead].frame = frame;
ringBufferHead = (ringBufferHead + 1) % RING_BUFFER_SIZE;
}
}
// Function to dequeue a video frame from the ring buffer
plm_frame_t *dequeueFrame() {
plm_frame_t *frame = NULL;
if (ringBufferHead != ringBufferTail) {
frame = ringBuffer[ringBufferTail].frame;
ringBufferTail = (ringBufferTail + 1) % RING_BUFFER_SIZE;
}
return frame;
}
#define UV_EPSILON 0.045f // Adjust the value as needed
#define screenWidth 640
#define screenHeight 480
void display_draw(void)
{
pvr_poly_cxt_t cxt;
pvr_poly_hdr_t hdr;
pvr_vertex_t vert;
float u = (float)width / (float)MPEG1_TEXTURE_WIDTH;
float v = (float)height / (float)MPEG1_TEXTURE_HEIGHT;
pvr_poly_cxt_txr(&cxt, PVR_LIST_OP_POLY, PVR_TXRFMT_YUV422 | PVR_TXRFMT_NONTWIDDLED, MPEG1_TEXTURE_WIDTH, MPEG1_TEXTURE_HEIGHT, texture, PVR_FILTER_TRILINEAR2);
pvr_poly_compile(&hdr, &cxt);
// hdr.mode3 |= 0x02000000; /* stride */
pvr_prim(&hdr, sizeof(hdr));
vert.argb = PVR_PACK_COLOR(1.0f, 1.0f, 1.0f, 1.0f);
vert.oargb = 0;
vert.flags = PVR_CMD_VERTEX;
vert.x = 1;
vert.y = 1;
vert.z = 1;
vert.u = UV_EPSILON;
vert.v = UV_EPSILON;
pvr_prim(&vert, sizeof(vert));
vert.x = screenWidth;
vert.y = 1;
vert.z = 1;
vert.u = u - UV_EPSILON;
vert.v = UV_EPSILON;
pvr_prim(&vert, sizeof(vert));
vert.x = 1;
vert.y = screenHeight;
vert.z = 1;
vert.u = UV_EPSILON;
vert.v = v - UV_EPSILON;
pvr_prim(&vert, sizeof(vert));
vert.x = screenWidth;
vert.y = screenHeight;
vert.z = 1;
vert.u = u - UV_EPSILON;
vert.v = v - UV_EPSILON;
vert.flags = PVR_CMD_VERTEX_EOL;
pvr_prim(&vert, sizeof(vert));
}
/* n must be multiple of 64 */
void dc_sq_cpy(void *dest, void *src, int n)
{
uint32 *sq;
uint32 *d, *s;
d = (uint32 *)(0xe0000000 | (((uint32)dest) & 0x03ffffe0));
s = (uint32 *)(src);
*((volatile unsigned int*)0xFF000038) = ((((uint32)dest)>>26)<<2)&0x1c;
*((volatile unsigned int*)0xFF00003C) = ((((uint32)dest)>>26)<<2)&0x1c;
n >>= 6;
while (n--)
{
// sq0
sq = d;
*sq++ = *s++; *sq++ = *s++;
*sq++ = *s++; *sq++ = *s++;
*sq++ = *s++; *sq++ = *s++;
*sq++ = *s++; *sq++ = *s++;
__asm__("pref @%0" : : "r" (d));
__asm__("ocbi @%0" : : "r" (d));
d += 8;
// sq1
sq = d;
*sq++ = *s++; *sq++ = *s++;
*sq++ = *s++; *sq++ = *s++;
*sq++ = *s++; *sq++ = *s++;
*sq++ = *s++; *sq++ = *s++;
__asm__("pref @%0" : : "r" (d));
__asm__("ocbi @%0" : : "r" (d));
d += 8;
}
*((uint32 *)(0xe0000000)) = 0;
*((uint32 *)(0xe0000020)) = 0;
}
void app_on_video(plm_t *mpeg, plm_frame_t *frame, void *user)
{
unsigned int *dest = (unsigned int *)texture;
unsigned int *src = (unsigned int *)frame->display;
volatile unsigned int *d = (volatile unsigned int *)0xa05f8148;
volatile unsigned int *cfg = (volatile unsigned int *)0xa05f814c;
volatile unsigned int *stride_reg = (volatile unsigned int *)0xa05f80e4;
int stride_value;
int stride = 0;
int x, y, w, h, i;
if (!frame)
return;
/* set frame size. */
w = frame->width >> 4;
h = frame->height >> 4;
stride_value = (w >> 1); /* 16 pixel / 2 */
/* Set Stride value. */
*stride_reg &= 0xffffffe0;
*stride_reg |= stride_value & 0x01f;
/* Set SQ to YUV converter. */
*d = ((unsigned int)dest) & 0xffffff;
*cfg = 0x00000f1f;
x = *cfg; /* read on once */
for (y = 0; y < h; y++)
{
for (x = 0; x < w; x++, src += 96)
{
dc_sq_cpy((void *)0x10800000, (void *)src, 384);
}
if (!stride)
{
/* Send dummy mb */
for (i = 0; i < 32 - w; i++)
{
sq_set((void *)0x10800000, 0, 384);
}
}
}
for (i = 0; i < 16 - h; i++)
{
if (!stride)
sq_set((void *)0x10800000, 0, 384 * 32);
else
sq_set((void *)0x10800000, 0, 384 * w);
}
}
// Define a buffer for audio samples
#define AUDIO_SAMPLE_BUFFER_SIZE (1152 * 2 * 10) // Adjust the size as needed
// Static variables for sound callback
static int mod_start = 0;
static int mod_size = 0;
static unsigned int audio_sample_buffer[AUDIO_SAMPLE_BUFFER_SIZE];
//Ian micheal added call back sound reset and buffer
// Function to reset sound callback's static variables
void reset_sound_callback()
{
mod_start = 0;
mod_size = 0;
}
// Sound callback function
// Sound callback function
void *sound_callback(snd_stream_hnd_t hnd, int size, int *size_out)
{
unsigned int *dest = audio_sample_buffer;
unsigned int *src = NULL; // Initialize src pointer
int out = 0;
// Prefetch the initial 'src' address
__asm__("pref @%0" : : "r" (src));
src = audio_sample_buffer + mod_start / 4;
for (int i = 0; i < mod_size / 4; i++) {
*dest++ = *src++;
// Prefetch the next memory location (adjust the distance as needed)
__asm__("pref @%0" : : "r" (src));
}
out += mod_size;
while (size > out)
{
plm_samples_t *sample = plm_decode_audio(plm);
if (sample == NULL)
{
reset_sound_callback(); // Reset static variables when audio ends
break;
}
// Prefetch the initial 'src' address for the audio samples
__asm__("pref @%0" : : "r" (src));
src = (unsigned int *)sample->pcm;
for (int i = 0; i < 1152 / 2; i++) {
*dest++ = *src++;
// Prefetch the next memory location (adjust the distance as needed)
__asm__("pref @%0" : : "r" (src));
}
out += 1152 * 2;
}
mod_start = size;
mod_size = out - size;
*size_out = size;
return (void *)audio_sample_buffer;
}
int Mpeg1Play(const char *filename, unsigned int buttons)
{
int cancel = 0;
plm = plm_create_with_filename(filename);
if (!plm)
return -1;
texture = pvr_mem_malloc(512 * 256 * 2);
width = plm_get_width(plm);
height = plm_get_height(plm);
// Initialize the ring buffer
initRingBuffer();
/* Set SQ to YUV converter. */
PVR_SET(PVR_YUV_ADDR, (((unsigned int)texture) & 0xffffff));
// Divide texture width and texture height by 16 and subtract 1.
// The actual values to set are 1, 3, 7, 15, 31, 63.
PVR_SET(PVR_YUV_CFG_1, (((MPEG1_TEXTURE_HEIGHT / 16) - 1) << 8) | ((MPEG1_TEXTURE_WIDTH / 16) - 1));
PVR_GET(PVR_YUV_CFG_1);
/* First frame */
plm_frame_t *frame = plm_decode_video(plm);
float start_time = (float)timer_ms_gettime64() / 1000.0;
float playing_time = 0.0f;
float frame_time = 1.0f / (float)plm_get_framerate(plm);
int decoded = 1;
//Ian micheal added call back sound reset and buffer
reset_sound_callback();
/* Init sound stream. */
int samplerate = plm_get_samplerate(plm);
snd_hnd = snd_stream_alloc(sound_callback, 0x10000);
snd_stream_volume(snd_hnd, 0xff);
snd_stream_queue_enable(snd_hnd);
snd_stream_start(snd_hnd, samplerate, 0);
snd_stream_queue_go(snd_hnd);
while (!cancel)
{
/* Check cancel buttons. */
if (buttons)
{
/* Check cancel buttons. */
MAPLE_FOREACH_BEGIN(MAPLE_FUNC_CONTROLLER, cont_state_t, st)
if (buttons && ((st->buttons & buttons) == buttons))
cancel = 1; /* Push cancel buttons */
if (st->buttons == 0x60e)
cancel = 2; /* ABXY + START (Software reset) */
MAPLE_FOREACH_END()
}
/* Decode */
playing_time = ((float)timer_ms_gettime64() / 1000.0) - start_time;
if ((frame->time - playing_time) < frame_time)
{
frame = plm_decode_video(plm);
if (!frame)
break;
decoded = 1;
// Enqueue the frame into the ring buffer
enqueueFrame(frame);
}
snd_stream_poll(snd_hnd);
/* Render */
pvr_wait_ready();
pvr_scene_begin();
if (decoded)
{
frame = dequeueFrame();
if (frame) {
app_on_video(plm, frame, 0);
}
decoded = 0;
}
pvr_list_begin(PVR_LIST_OP_POLY);
display_draw();
pvr_list_finish();
pvr_scene_finish();
}
//Ian micheal added call back sound reset and buffer
reset_sound_callback();
plm_destroy(plm);
pvr_mem_free(texture);
snd_stream_destroy(snd_hnd);
return cancel;
}
Code: Select all
ffmpeg -i input.mp4 -vf "scale=320:240" -b:v 642k -ac 1 -ar 44100 -c:a mp2 -b:a 64k -f mpg output.mpeg
Code: Select all
ffmpeg -i input.mp4 -vf "scale=320:240" -b:v 642k -minrate 642k -maxrate 642k -bufsize 642k -ac 1 -ar 44100 -c:a mp2 -b:a 64k -f mpeg output.mpg
Ok after many cdrs burned today i found best
video sample
https://streamable.com/leic1n
[code]ffmpeg -i input.mp4 -vf "scale=320:240" -b:v 742k -minrate 742k -maxrate 742k -bufsize 742k -ac 1 -ar 32000 -c:a mp2 -b:a 64k -f mpeg output.mpg
Example video of HQ again OLE tv demo lol
https://streamable.com/35gj9y
- These users thanked the author Ian Robinson for the post (total 2):
- |darc| • Twada
-
- DC Developer
- Posts: 48
- Joined: Wed Jan 20, 2016 4:55 am
- Has thanked: 20 times
- Been thanked: 56 times
Re: pl_mpegDC ported running but community help needed
Thank you for your detailed verification.
The 64-byte original store queue is also cool. Please merge anytime.
I realized something important thanks to your sample video.
There seems to be a bug in video decoding. U and V are flickering in YUV. This is especially evident in the Universal logo on the Jurassic Park trailer.
Please wait while we identify the issue...
The 64-byte original store queue is also cool. Please merge anytime.
I realized something important thanks to your sample video.
There seems to be a bug in video decoding. U and V are flickering in YUV. This is especially evident in the Universal logo on the Jurassic Park trailer.
Please wait while we identify the issue...
- These users thanked the author Twada for the post:
- Ian Robinson
- Ian Robinson
- DC Developer
- Posts: 126
- Joined: Mon Mar 11, 2019 7:12 am
- Has thanked: 225 times
- Been thanked: 45 times
Re: pl_mpegDC ported running but community help needed
I did notice that can see it even on the sample video you did but very much not notice-able..Twada wrote: ↑Wed Sep 27, 2023 6:36 pm Thank you for your detailed verification.
The 64-byte original store queue is also cool. Please merge anytime.
I realized something important thanks to your sample video.
There seems to be a bug in video decoding. U and V are flickering in YUV. This is especially evident in the Universal logo on the Jurassic Park trailer.
Please wait while we identify the issue...
I'm going to profile the code find out more with https://gitlab.com/simulant/dcprof/tree/master
Code: Select all
sh-elf-gprof.exe YOUR.elf gmon.out > gprof.out
Code: Select all
cat gprof.out | gprof2dot | dot -Tpng -o output.png
- Ian Robinson
- DC Developer
- Posts: 126
- Joined: Mon Mar 11, 2019 7:12 am
- Has thanked: 225 times
- Been thanked: 45 times
Re: pl_mpegDC ported running but community help needed
Ok i did the profiling to see the bottlenecks whats taking the most time..
when it first starts When it plays longer As it plays longer you can see it gets more heavy
seems strange but i do see it we have to look at this.
when it first starts When it plays longer As it plays longer you can see it gets more heavy
seems strange but i do see it we have to look at this.
- These users thanked the author Ian Robinson for the post:
- Twada
-
- DC Developer
- Posts: 48
- Joined: Wed Jan 20, 2016 4:55 am
- Has thanked: 20 times
- Been thanked: 56 times
Re: pl_mpegDC ported running but community help needed
I see, this is how profiling can be used! It is very easy to see where the bottleneck is.Ian Robinson wrote: ↑Wed Sep 27, 2023 8:50 pm Ok i did the profiling to see the bottlenecks whats taking the most time..
when it first starts
output.png
When it plays longer
output.png
As it plays longer you can see it gets more heavy
seems strange but i do see it we have to look at this.
We need to fix the problem that slows down when playing videos for a long time. Is there a memory leak occurring somewhere?
Your profiling can help. Please give me some time.
Fixed UV flickering. It was my mistake.
Please replace pl_mpeg.h.
- These users thanked the author Twada for the post:
- Ian Robinson
- Ian Robinson
- DC Developer
- Posts: 126
- Joined: Mon Mar 11, 2019 7:12 am
- Has thanked: 225 times
- Been thanked: 45 times
Re: pl_mpegDC ported running but community help needed
That fixed itTwada wrote: ↑Fri Sep 29, 2023 2:48 amI see, this is how profiling can be used! It is very easy to see where the bottleneck is.Ian Robinson wrote: ↑Wed Sep 27, 2023 8:50 pm Ok i did the profiling to see the bottlenecks whats taking the most time..
when it first starts
output.png
When it plays longer
output.png
As it plays longer you can see it gets more heavy
seems strange but i do see it we have to look at this.
We need to fix the problem that slows down when playing videos for a long time. Is there a memory leak occurring somewhere?
Your profiling can help. Please give me some time.
Fixed UV flickering. It was my mistake.
Please replace pl_mpeg.h.
pl_mpeg.h
Demo video
https://streamable.com/etk2bo
- Ian Robinson
- DC Developer
- Posts: 126
- Joined: Mon Mar 11, 2019 7:12 am
- Has thanked: 225 times
- Been thanked: 45 times
Re: pl_mpegDC ported running but community help needed
I will show known problem with the sh4 target and loop unrolling i can get up to 12% more time just doing loop unrolling by hand.
Dont know if seen this https://github.com/DragonMinded/libdrag ... 34a8ae9c7c
Loop unroll test https://gist.github.com/pcercuei/051c97 ... a2936d600e
I will profile and show it started on it you can see it lower time.
Not sure of a memory leak i have had it run over 30 mins watching a show and it never crashed.
Dont know if seen this https://github.com/DragonMinded/libdrag ... 34a8ae9c7c
Loop unroll test https://gist.github.com/pcercuei/051c97 ... a2936d600e
I will profile and show it started on it you can see it lower time.
Not sure of a memory leak i have had it run over 30 mins watching a show and it never crashed.
- Ian Robinson
- DC Developer
- Posts: 126
- Joined: Mon Mar 11, 2019 7:12 am
- Has thanked: 225 times
- Been thanked: 45 times
Re: pl_mpegDC ported running but community help needed
Ok been optimizing
before after I have to do a number of tests and i update the SQCOPY and SQSET
Seeing nice improvement.
before after I have to do a number of tests and i update the SQCOPY and SQSET
Seeing nice improvement.
- These users thanked the author Ian Robinson for the post:
- Twada
-
- DC Developer
- Posts: 48
- Joined: Wed Jan 20, 2016 4:55 am
- Has thanked: 20 times
- Been thanked: 56 times
Re: pl_mpegDC ported running but community help needed
Fixed to synchronize with audio time.
Once the video lags, it should catch up with the audio.
However, videos without audio are not eligible.
I decided to unify my handle name to Twada. Because it's complicated...
Once the video lags, it should catch up with the audio.
However, videos without audio are not eligible.
I decided to unify my handle name to Twada. Because it's complicated...
- These users thanked the author Twada for the post:
- Ian Robinson
- Ian Robinson
- DC Developer
- Posts: 126
- Joined: Mon Mar 11, 2019 7:12 am
- Has thanked: 225 times
- Been thanked: 45 times
Re: pl_mpegDC ported running but community help needed
With my update before been able to watch 1 hour with no sync problems audio with the right encoding.
- These users thanked the author Ian Robinson for the post:
- |darc|