static bool video_frame(struct ff_frame *frame, void *opaque) { struct ffmpeg_source *s = opaque; struct obs_source_frame obs_frame = {0}; uint64_t pts; // Media ended if (frame == NULL) { if (s->is_clear_on_media_end) obs_source_output_video(s->source, NULL); return true; } pts = (uint64_t)(frame->pts * 1000000000.0L); obs_frame.timestamp = pts; obs_frame.width = frame->frame->width; obs_frame.height = frame->frame->height; enum video_format format = ffmpeg_to_obs_video_format(frame->frame->format); if (s->is_forcing_scale || format == VIDEO_FORMAT_NONE) return video_frame_scale(frame, s, &obs_frame); else if (s->is_hw_decoding) return video_frame_hwaccel(frame, s, &obs_frame); else return video_frame_direct(frame, s, &obs_frame); }
/** * video_frame: * @data : pointer to data of the video frame. * @width : width of the video frame. * @height : height of the video frame. * @pitch : pitch of the video frame. * * Video frame render callback function. **/ static void video_frame(const void *data, unsigned width, unsigned height, size_t pitch) { unsigned output_width = 0, output_height = 0, output_pitch = 0; const char *msg = NULL; driver_t *driver = driver_get_ptr(); global_t *global = global_get_ptr(); settings_t *settings = config_get_ptr(); if (!driver->video_active) return; video_driver_cached_frame_set(data, width, height, pitch); if (video_frame_scale(data, width, height, pitch)) { data = driver->scaler_out; pitch = driver->scaler.out_stride; } /* Slightly messy code, * but we really need to do processing before blocking on VSync * for best possible scheduling. */ if ((!video_driver_frame_filter_alive() || !settings->video.post_filter_record || !data || global->record.gpu_buffer) ) recording_dump_frame(data, width, height, pitch); msg = rarch_main_msg_queue_pull(); driver->current_msg = msg; if (video_driver_frame_filter(data, width, height, pitch, &output_width, &output_height, &output_pitch)) { data = video_driver_frame_filter_get_buf_ptr(); width = output_width; height = output_height; pitch = output_pitch; } if (!video_driver_frame(data, width, height, pitch, msg)) driver->video_active = false; }