static void tsmf_presentation_restore_last_video_frame(TSMF_PRESENTATION* presentation) { RDP_REDRAW_EVENT* revent; if (presentation->last_width && presentation->last_height) { revent = (RDP_REDRAW_EVENT*) freerdp_event_new(TsmfChannel_Class, TsmfChannel_Redraw, NULL, NULL); revent->x = presentation->last_x; revent->y = presentation->last_y; revent->width = presentation->last_width; revent->height = presentation->last_height; if (!tsmf_push_event(presentation->channel_callback, (wMessage*) revent)) { freerdp_event_free((wMessage*) revent); } presentation->last_x = 0; presentation->last_y = 0; presentation->last_width = 0; presentation->last_height = 0; } }
static void tsmf_presentation_restore_last_video_frame(TSMF_PRESENTATION* presentation) { RDP_REDRAW_EVENT* revent; if (presentation->last_width && presentation->last_height) { revent = (RDP_REDRAW_EVENT*) freerdp_event_new(RDP_EVENT_CLASS_TSMF, RDP_EVENT_TYPE_TSMF_REDRAW, NULL, NULL); revent->x = presentation->last_x; revent->y = presentation->last_y; revent->width = presentation->last_width; revent->height = presentation->last_height; if (!tsmf_push_event(presentation->channel_callback, (RDP_EVENT*) revent)) { freerdp_event_free((RDP_EVENT*) revent); } presentation->last_x = 0; presentation->last_y = 0; presentation->last_width = 0; presentation->last_height = 0; } }
static void tsmf_sample_playback_video(TSMF_SAMPLE* sample) { UINT64 t; RDP_VIDEO_FRAME_EVENT* vevent; TSMF_STREAM* stream = sample->stream; TSMF_PRESENTATION* presentation = stream->presentation; DEBUG_DVC("MessageId %d EndTime %d data_size %d consumed.", sample->sample_id, (int)sample->end_time, sample->data_size); if (sample->data) { t = get_current_time(); if (stream->next_start_time > t && (sample->end_time >= presentation->audio_start_time || sample->end_time < stream->last_end_time)) { USleep((stream->next_start_time - t) / 10); } stream->next_start_time = t + sample->duration - 50000; if (presentation->last_x != presentation->output_x || presentation->last_y != presentation->output_y || presentation->last_width != presentation->output_width || presentation->last_height != presentation->output_height || presentation->last_num_rects != presentation->output_num_rects || (presentation->last_rects && presentation->output_rects && memcmp(presentation->last_rects, presentation->output_rects, presentation->last_num_rects * sizeof(RDP_RECT)) != 0)) { tsmf_presentation_restore_last_video_frame(presentation); presentation->last_x = presentation->output_x; presentation->last_y = presentation->output_y; presentation->last_width = presentation->output_width; presentation->last_height = presentation->output_height; if (presentation->last_rects) { free(presentation->last_rects); presentation->last_rects = NULL; } presentation->last_num_rects = presentation->output_num_rects; if (presentation->last_num_rects > 0) { presentation->last_rects = malloc(presentation->last_num_rects * sizeof(RDP_RECT)); ZeroMemory(presentation->last_rects, presentation->last_num_rects * sizeof(RDP_RECT)); memcpy(presentation->last_rects, presentation->output_rects, presentation->last_num_rects * sizeof(RDP_RECT)); } } vevent = (RDP_VIDEO_FRAME_EVENT*) freerdp_event_new(TsmfChannel_Class, TsmfChannel_VideoFrame, NULL, NULL); vevent->frame_data = sample->data; vevent->frame_size = sample->decoded_size; vevent->frame_pixfmt = sample->pixfmt; vevent->frame_width = sample->stream->width; vevent->frame_height = sample->stream->height; vevent->x = presentation->output_x; vevent->y = presentation->output_y; vevent->width = presentation->output_width; vevent->height = presentation->output_height; if (presentation->output_num_rects > 0) { vevent->num_visible_rects = presentation->output_num_rects; vevent->visible_rects = (RDP_RECT*) malloc(presentation->output_num_rects * sizeof(RDP_RECT)); ZeroMemory(vevent->visible_rects, presentation->output_num_rects * sizeof(RDP_RECT)); memcpy(vevent->visible_rects, presentation->output_rects, presentation->output_num_rects * sizeof(RDP_RECT)); } /* The frame data ownership is passed to the event object, and is freed after the event is processed. */ sample->data = NULL; sample->decoded_size = 0; if (!tsmf_push_event(sample->channel_callback, (wMessage*) vevent)) { freerdp_event_free((wMessage*) vevent); } #if 0 /* Dump a .ppm image for every 30 frames. Assuming the frame is in YUV format, we extract the Y values to create a grayscale image. */ static int frame_id = 0; char buf[100]; FILE * fp; if ((frame_id % 30) == 0) { snprintf(buf, sizeof(buf), "/tmp/FreeRDP_Frame_%d.ppm", frame_id); fp = fopen(buf, "wb"); fwrite("P5\n", 1, 3, fp); snprintf(buf, sizeof(buf), "%d %d\n", sample->stream->width, sample->stream->height); fwrite(buf, 1, strlen(buf), fp); fwrite("255\n", 1, 4, fp); fwrite(sample->data, 1, sample->stream->width * sample->stream->height, fp); fflush(fp); fclose(fp); } frame_id++; #endif } }