int ffplay(const char *filename, const char *force_format) { char errbuf[256]; int r = 0; int frameFinished; AVPacket packet; int audio_buf_size = AVCODEC_MAX_AUDIO_FRAME_SIZE; int16_t *audio_buf = (int16_t *) malloc((AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2); if(!audio_buf) { ds_printf("DS_ERROR: No free memory\n"); return -1; } memset(audio_buf, 0, (AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2); AVFormatContext *pFormatCtx = NULL; AVFrame *pFrame = NULL; AVCodecContext *pVideoCodecCtx = NULL, *pAudioCodecCtx = NULL; AVInputFormat *file_iformat = NULL; video_txr_t movie_txr; int videoStream = -1, audioStream = -1; maple_device_t *cont = NULL; cont_state_t *state = NULL; int pause = 0, done = 0; char fn[MAX_FN_LEN]; sprintf(fn, "ds:%s", filename); memset(&movie_txr, 0, sizeof(movie_txr)); if(!codecs_inited) { avcodec_register_all(); avcodec_register(&mp1_decoder); avcodec_register(&mp2_decoder); avcodec_register(&mp3_decoder); avcodec_register(&vorbis_decoder); //avcodec_register(&mpeg4_decoder); codecs_inited = 1; } if(force_format) file_iformat = av_find_input_format(force_format); else file_iformat = NULL; // Open video file ds_printf("DS_PROCESS_FFMPEG: Opening file: %s\n", filename); if((r = av_open_input_file((AVFormatContext**)(&pFormatCtx), fn, file_iformat, /*FFM_PACKET_SIZE*/0, NULL)) != 0) { av_strerror(r, errbuf, 256); ds_printf("DS_ERROR_FFMPEG: %s\n", errbuf); free(audio_buf); return -1; // Couldn't open file } // Retrieve stream information ds_printf("DS_PROCESS_FFMPEG: Retrieve stream information...\n"); if((r = av_find_stream_info(pFormatCtx)) < 0) { av_strerror(r, errbuf, 256); ds_printf("DS_ERROR_FFMPEG: %s\n", errbuf); av_close_input_file(pFormatCtx); free(audio_buf); return -1; // Couldn't find stream information } // Dump information about file onto standard error dump_format(pFormatCtx, 0, filename, 0); //thd_sleep(5000); pVideoCodecCtx = findDecoder(pFormatCtx, AVMEDIA_TYPE_VIDEO, &videoStream); pAudioCodecCtx = findDecoder(pFormatCtx, AVMEDIA_TYPE_AUDIO, &audioStream); //LockInput(); if(pVideoCodecCtx) { //LockVideo(); ShutdownVideoThread(); SDL_DS_FreeScreenTexture(0); int format = 0; switch(pVideoCodecCtx->pix_fmt) { case PIX_FMT_YUV420P: case PIX_FMT_YUVJ420P: format = PVR_TXRFMT_YUV422; #ifdef USE_HW_YUV yuv_conv_init(); #endif break; case PIX_FMT_UYVY422: case PIX_FMT_YUVJ422P: format = PVR_TXRFMT_YUV422; break; default: format = PVR_TXRFMT_RGB565; break; } MakeVideoTexture(&movie_txr, pVideoCodecCtx->width, pVideoCodecCtx->height, format | PVR_TXRFMT_NONTWIDDLED, PVR_FILTER_BILINEAR); #ifdef USE_HW_YUV yuv_conv_setup(movie_txr.addr, PVR_YUV_MODE_MULTI, PVR_YUV_FORMAT_YUV420, movie_txr.width, movie_txr.height); pvr_dma_init(); #endif } else { ds_printf("DS_ERROR: Didn't find a video stream.\n"); } if(pAudioCodecCtx) { #ifdef USE_DIRECT_AUDIO audioinit(pAudioCodecCtx); #else sprintf(fn, "%s/firmware/aica/ds_stream.drv", getenv("PATH")); if(snd_init_fw(fn) < 0) { goto exit_free; } if(aica_audio_open(pAudioCodecCtx->sample_rate, pAudioCodecCtx->channels, 8192) < 0) { goto exit_free; } //snd_cpu_clock(0x19); //snd_init_decoder(8192); #endif } else { ds_printf("DS_ERROR: Didn't find a audio stream.\n"); } //ds_printf("FORMAT: %d\n", pVideoCodecCtx->pix_fmt); // Allocate video frame pFrame = avcodec_alloc_frame(); if(pFrame == NULL) { ds_printf("DS_ERROR: Can't alloc memory\n"); goto exit_free; } int pressed = 0, framecnt = 0; uint32 fa = 0; fa = GET_EXPORT_ADDR("ffplay_format_handler"); if(fa > 0 && fa != 0xffffffff) { EXPT_GUARD_BEGIN; void (*ff_format_func)(AVFormatContext *, AVCodecContext *, AVCodecContext *) = (void (*)(AVFormatContext *, AVCodecContext *, AVCodecContext *))fa; ff_format_func(pFormatCtx, pVideoCodecCtx, pAudioCodecCtx); EXPT_GUARD_CATCH; EXPT_GUARD_END; } fa = GET_EXPORT_ADDR("ffplay_frame_handler"); void (*ff_frame_func)(AVFrame *) = NULL; if(fa > 0 && fa != 0xffffffff) { EXPT_GUARD_BEGIN; ff_frame_func = (void (*)(AVFrame *))fa; // Test call ff_frame_func(NULL); EXPT_GUARD_CATCH; ff_frame_func = NULL; EXPT_GUARD_END; } fa = GET_EXPORT_ADDR("ffplay_render_handler"); if(fa > 0 && fa != 0xffffffff) { EXPT_GUARD_BEGIN; movie_txr.render_cb = (void (*)(void *))fa; // Test call movie_txr.render_cb(NULL); EXPT_GUARD_CATCH; movie_txr.render_cb = NULL; EXPT_GUARD_END; } while(av_read_frame(pFormatCtx, &packet) >= 0 && !done) { do { if(ff_frame_func) ff_frame_func(pFrame); cont = maple_enum_type(0, MAPLE_FUNC_CONTROLLER); framecnt++; if(cont) { state = (cont_state_t *)maple_dev_status(cont); if (!state) { break; } if (state->buttons & CONT_START || state->buttons & CONT_B) { av_free_packet(&packet); done = 1; } if (state->buttons & CONT_A) { if((framecnt - pressed) > 10) { pause = pause ? 0 : 1; if(pause) { #ifdef USE_DIRECT_AUDIO audio_end(); #else stop_audio(); #endif } else { #ifndef USE_DIRECT_AUDIO start_audio(); #endif } } pressed = framecnt; } if(state->buttons & CONT_DPAD_LEFT) { //av_seek_frame(pFormatCtx, -1, timestamp * ( AV_TIME_BASE / 1000 ), AVSEEK_FLAG_BACKWARD); } if(state->buttons & CONT_DPAD_RIGHT) { //av_seek_frame(pFormatCtx, -1, timestamp * ( AV_TIME_BASE / 1000 ), AVSEEK_FLAG_BACKWARD); } } if(pause) thd_sleep(100); } while(pause); //printf("Packet: size: %d data: %02x%02x%02x pst: %d\n", packet.size, packet.data[0], packet.data[1], packet.data[2], pFrame->pts); // Is this a packet from the video stream? if(packet.stream_index == videoStream) { //printf("video\n"); // Decode video frame if((r = avcodec_decode_video2(pVideoCodecCtx, pFrame, &frameFinished, &packet)) < 0) { //av_strerror(r, errbuf, 256); //printf("DS_ERROR_FFMPEG: %s\n", errbuf); } else { // Did we get a video frame? if(frameFinished && !pVideoCodecCtx->hurry_up) { RenderVideo(&movie_txr, pFrame, pVideoCodecCtx); } } } else if(packet.stream_index == audioStream) { //printf("audio\n"); //snd_decode((uint8*)audio_buf, audio_buf_size, AICA_CODEC_MP3); audio_buf_size = AVCODEC_MAX_AUDIO_FRAME_SIZE; if((r = avcodec_decode_audio3(pAudioCodecCtx, audio_buf, &audio_buf_size, &packet)) < 0) { //av_strerror(r, errbuf, 256); //printf("DS_ERROR_FFMPEG: %s\n", errbuf); //continue; } else { if(audio_buf_size > 0 && !pAudioCodecCtx->hurry_up) { #ifdef USE_DIRECT_AUDIO audio_write(pAudioCodecCtx, audio_buf, audio_buf_size); #else aica_audio_write((char*)audio_buf, audio_buf_size); #endif } } } // Free the packet that was allocated by av_read_frame av_free_packet(&packet); } goto exit_free; exit_free: if(pFrame) av_free(pFrame); if(pFormatCtx) av_close_input_file(pFormatCtx); if(audioStream > -1) { if(pAudioCodecCtx) avcodec_close(pAudioCodecCtx); #ifdef USE_DIRECT_AUDIO audio_end(); #else aica_audio_close(); sprintf(fn, "%s/firmware/aica/kos_stream.drv", getenv("PATH")); snd_init_fw(fn); #endif } if(audio_buf) { free(audio_buf); } if(videoStream > -1) { if(pVideoCodecCtx) avcodec_close(pVideoCodecCtx); FreeVideoTexture(&movie_txr); SDL_DS_AllocScreenTexture(GetScreen()); InitVideoThread(); //UnlockVideo(); } //UnlockInput(); ProcessVideoEventsUpdate(NULL); return 0; }
/** * Init_Genesis(): Initialize the Genesis with the specified ROM image. * @param MD_ROM ROM image struct. * @return 1 if successful. */ int Init_Genesis(ROM_t* MD_ROM) { // Clear the sound buffer. audio_clear_sound_buffer(); Flag_Clr_Scr = 1; Settings.Paused = Frame_Number = 0; SRAM_Start = SRAM_End = SRAM_ON = SRAM_Write = 0; Controller_1_COM = Controller_2_COM = 0; #ifdef GENS_DEBUGGER STOP_DEBUGGING(); #endif #if 0 // TODO: Replace with MDP "exclusive mode" later. if (!Kaillera_Client_Running) #endif Init_Genesis_SRAM(MD_ROM); // Check what country code should be used. // TODO: Get rid of magic numbers. switch (Country) { default: case -1: // Autodetection. Detect_Country_Genesis(MD_ROM); break; case 0: // Japan (NTSC) Game_Mode = 0; CPU_Mode = 0; break; case 1: // US (NTSC) Game_Mode = 1; CPU_Mode = 0; break; case 2: // Europe (PAL) Game_Mode = 1; CPU_Mode = 1; break; case 3: // Japan (PAL) Game_Mode = 0; CPU_Mode = 1; break; } VDP_Num_Vis_Lines = 224; Gen_Version = 0x20 + 0x0; // Version de la megadrive (0x0 - 0xF) // Byteswap the ROM data. be16_to_cpu_array(Rom_Data, Rom_Size); ROM_ByteSwap_State |= ROM_BYTESWAPPED_MD_ROM; // Reset all CPUs and other components. M68K_Reset(0); Z80_Reset(); VDP_Reset(); // Initialize the controller state. Init_Controllers(); // Set clock rates depending on the CPU mode (NTSC / PAL). Set_Clock_Freq(0); // If auto-fix checksum is enabled, fix the ROM checksum. if (Auto_Fix_CS) ROM::fixChecksum(); // Initialize sound. if (audio_get_enabled()) { audio_end(); if (audio_init(AUDIO_BACKEND_DEFAULT)) audio_set_enabled(false); else { if (audio_play_sound) audio_play_sound(); } } Reset_Update_Timers(); // Set the appropriate frame update function pointers. Update_Frame = Do_Genesis_Frame; Update_Frame_Fast = Do_Genesis_Frame_No_VDP; return 1; }