Рендеринг потокового видео (FMV, Full Motion Video) на PlayStation 1 — это сложный процесс, сочетающий чтение данных с CD-ROM, декодирование через MDEC (Motion DECoder) и вывод на экран через GPU. Вот пошаговое объяснение: --- ### **1. Подготовка данных на диске** - Видео хранится в специальном формате **STR** (Sony's Video Format), который содержит: - **Видеопоток** — сжатый через MPEG-1 (но упрощённый для PS1). - **Аудиопоток** — ADPCM или CD-DA (Red Book Audio). - **Субтитры/тайминг** — дополнительные данные. Данные разбиты на **секторы CD-ROM (Mode 2 XA)**, где чередуются видео и аудио. --- ### **2. Загрузка данных с CD-ROM** 1. **CPU отправляет команду чтения**: ```c CdReadSector(/*Сектор начала*/, /*Кол-во секторов*/, /*Буфер в RAM*/); ``` 2. **DMA (канал 3) копирует данные** из буфера CD-ROM в RAM: - Используется **двойная буферизация**: - Пока DMA заполняет **Буфер 1**, CPU/MDEC обрабатывает **Буфер 2**. - Размер буфера обычно **16–32 КБ** (8–16 секторов). 3. **Ожидание завершения**: ```c CdReadSync(0); // Блокирующее ожидание ``` --- ### **3. Декодирование видео через MDEC** 1. **CPU настраивает MDEC** (канал DMA 0/1): - Указывает адрес сжатых данных в RAM. - Запускает декодирование: ```asm li t0, 0x1F801820 // MDEC_CMD li t1, 0x60000000 // Команда "Decode Macroblock" sw t1, 0(t0) ``` 2. **MDEC декодирует MPEG-1**: - Кадр разбит на **макроблоки 16x16**. - Используется **DCT (Discrete Cosine Transform)** + **RLE (Run-Length Encoding)**. - На выходе — **RGB16 (15-битный)** или **YUV** пиксели. 3. **DMA (канал 1) копирует результат** в RAM: - Готовые кадры сохраняются в **отдельный буфер** (например, 320x240, 16-бит). --- ### **4. Вывод на экран через GPU** 1. **CPU отправляет кадр в VRAM**: - Через DMA (канал 2) или вручную (порт `GP0`). - Пример: ```asm li a0, 0x1F8010A0 // DMA GPU (канал 2) la a1, frame_buffer sw a1, 0(a0) // Источник li a1, 0x01000200 // Размер + режим sw a1, 4(a0) ``` 2. **GPU выводит кадр**: - Используется **полноэкранный спрайт** (Rectangular Texture). - Команда: ```asm li t0, 0x1F801810 // GP0 li t1, 0xA0000000 // Команда "Draw Rectangle" sw t1, 0(t0) ``` 3. **Синхронизация с VBlank**: - Чтобы избежать артефактов, обновление кадра происходит **во время VBlank**: ```c VSync(0); ``` --- ### **5. Аудиосопровождение** - **ADPCM-аудио** декодируется через SPU (канал DMA 4): ```c SpuSetTransferMode(SPU_TRANSFER_BY_DMA); SpuWrite(audio_buffer, audio_size); ``` - **CD-DA (Red Book)** воспроизводится напрямую с диска (аппаратно). --- ### **6. Оптимизации** 1. **Чередование данных (Interleaving)**: - Видео и аудио секторы чередуются на диске для плавности. - Пример структуры: ``` [VIDEO] [AUDIO] [VIDEO] [AUDIO]... ``` 2. **Предзагрузка**: - Игры заранее грузят несколько кадров в память. 3. **Пропуск кадров**: - Если декодирование не успевает, PS1 пропускает кадры (например, в Resident Evil). --- ### **7. Пример кода (упрощённый цикл FMV)** ```c void play_fmv() { uint8_t video_buffer[32768]; uint16_t frame_buffer[320*240]; while (!fmv_finished) { // 1. Чтение с CD-ROM CdReadSector(current_sector, 16, video_buffer); CdReadSync(0); // 2. Декодирование через MDEC MDEC_DecodeFrame(video_buffer, frame_buffer); // 3. Вывод через GPU GPU_SendFrame(frame_buffer); // 4. Синхронизация VSync(0); current_sector += 16; } } ``` --- ### **8. Проблемы и ограничения** - **Низкое разрешение**: 320x240 (чаще 256x224 для экономии памяти). - **Цветовые артефакты**: Из-за 15-битного RGB. - **Задержки**: Если CD-ROM не успевает, видео тормозит. --- ### **Итог** 1. **Чтение** с CD-ROM через DMA. 2. **Декодирование** через MDEC. 3. **Вывод** через GPU. 4. **Синхронизация** с VBlank. ----------------- # Функция `DecDCTvlc2` в библиотеке PsyQ для PlayStation 1 Функция `DecDCTvlc2` является частью аппаратно-оптимизированной библиотеки декодирования видеоданных в реальном времени для PlayStation 1. Она выполняет декодирование **переменнодлинных кодов (VLC - Variable Length Coding)** в процессе декомпрессии **DCT (Discrete Cosine Transform)** данных, обычно используемых в видеоформатах типа MPEG. ## Основное назначение `DecDCTvlc2` декодирует: 1. Битовые потоки с переменнодлинным кодированием (VLC) 2. Коэффициенты DCT после обратного зигзаг-сканирования 3. Данные в формате, используемом аппаратным декодером PS1 ## Технические детали ```c void DecDCTvlc2(unsigned short *data, int *macroblock); ``` Где: - `data` - указатель на входной битовый поток VLC - `macroblock` - указатель на выходной буфер для декодированных данных макроблока (6 блоков по 64 элемента: 4 яркостных, 2 цветностных) ## Особенности реализации 1. **Аппаратное ускорение** - использует специальные возможности графического процессора PS1 2. **Оптимизировано для MPEG-подобных потоков** - но не является полным MPEG-декодером 3. **Работает с макроблоками** - 16x16 пикселей (4 блока яркости Y, 1 блок каждой цветности Cr/Cb) 4. **Требует предварительной настройки** - через `DecDCTin()`, `DecDCTout()` и другие функции видеоцепи ## Пример использования ```c #include #include #include #include #include void decode_video_frame(unsigned short *vlc_data) { // Буфер для декодированного макроблока (6 блоков по 64 коэффициента) int macroblock[6*64]; // Настройка ввода/вывода декодера DecDCTin(vlc_data, 0); DecDCTout((unsigned char*)macroblock, 0); // Декодирование VLC-потока DecDCTvlc2(vlc_data, macroblock); // Дальнейшая обработка декодированных данных... } ``` ## Типичный контекст использования 1. **Декодирование внутрикадровых (I-кадров) MPEG-видео** 2. **Обработка видеопотоков в реальном времени** 3. **Специальные эффекты с использованием DCT-данных** 4. **Собственные алгоритмы видеокомпрессии** ## Важные нюансы 1. **Не является полным MPEG-декодером** - требует дополнительной логики для полного декодирования видео 2. **Требует точного соответствия формату данных** - входной поток должен быть правильно сформирован 3. **Работает в паре с другими функциями DCT-цепи**: - `DecDCTin()` - настройка входного буфера - `DecDCTout()` - настройка выходного буфера - `DecDCToutCallback()` - установка callback'а по завершении 4. **Использует аппаратные возможности PS1** - дает значительный выигрыш в производительности по сравнению с программной реализацией Функция `DecDCTvlc2` представляет собой низкоуровневый инструмент для работы с видео на PS1 и требует глубокого понимания принципов DCT-компрессии и форматов видеоданных, используемых на этой платформе.