static int display_frame(X11DisplaySink* sink, X11DisplayFrame* frame, const FrameInfo* frameInfo) { struct timeval timeNow; long requiredUsec; long durationSlept; YUV_frame inputFrame; YUV_frame outputFrame; unsigned char* inputBuffer; unsigned char* rgbInputBuffer; StreamFormat rgbInputFormat; int frameDurationMsec; int frameSlippage; frameDurationMsec = (int)(1000 * frameInfo->frameRate.den / (double)(frameInfo->frameRate.num)); frameSlippage = frameDurationMsec * 1000 / 2; /* half a frame */ if (frame->videoIsPresent) { if (frame->videoFormat == UYVY_10BIT_FORMAT) { DitherFrame(frame->convertBuffer, frame->inputBuffer, sink->inputWidth * 2, (sink->inputWidth + 5) / 6 * 16, sink->inputWidth, sink->inputHeight); inputBuffer = frame->convertBuffer; rgbInputFormat = UYVY_FORMAT; } else { inputBuffer = frame->inputBuffer; rgbInputFormat = frame->videoFormat; } /* scale image */ if (sink->swScale != 1) { YUV_frame_from_buffer(&inputFrame, (void*)inputBuffer, sink->inputWidth, sink->inputHeight, sink->yuvFormat); YUV_frame_from_buffer(&outputFrame, (void*)frame->scaleBuffer, sink->width, sink->height, sink->yuvFormat); small_pic(&inputFrame, &outputFrame, 0, 0, sink->swScale, sink->swScale, 1, 1, 1, frame->scaleWorkspace); rgbInputBuffer = frame->scaleBuffer; } else { rgbInputBuffer = inputBuffer; } /* add OSD to frame */ if (sink->osd != NULL && sink->osdInitialised) { if (!osd_add_to_image(sink->osd, frameInfo, rgbInputBuffer, sink->width, sink->height)) { ml_log_error("Failed to add OSD to frame\n"); /* continue anyway */ } } /* convert frame to RGB */ convertToRGB(sink, rgbInputFormat, rgbInputBuffer, frame->rgbBuffer, sink->width, sink->height); /* wait until it is time to display this frame */ gettimeofday(&timeNow, NULL); durationSlept = 0; if (frameInfo->rateControl) { durationSlept = sleep_diff(frameDurationMsec * 1000, &timeNow, &sink->lastFrameTime); } XLockDisplay(sink->x11Common.windowInfo.display); if (sink->useSharedMemory) { XShmPutImage(sink->x11Common.windowInfo.display, sink->x11Common.windowInfo.window, sink->x11Common.windowInfo.gc, frame->xImage, 0, 0, 0, 0, sink->width, sink->height, False); } else { XPutImage(sink->x11Common.windowInfo.display, sink->x11Common.windowInfo.window, sink->x11Common.windowInfo.gc, frame->xImage, 0, 0, 0, 0, sink->width, sink->height); } XSync(sink->x11Common.windowInfo.display, False); XUnlockDisplay(sink->x11Common.windowInfo.display); x11c_process_events(&sink->x11Common); /* report that a new frame has been displayed */ msl_frame_displayed(sink->listener, frameInfo); /* set the time that this frame was displayed */ if (frameInfo->rateControl) { if (durationSlept < - frameSlippage) { /* reset rate control when slipped by more than frameSlippage */ sink->lastFrameTime = timeNow; } else { /* set what the frame's display time should have been */ requiredUsec = sink->lastFrameTime.tv_sec * 1000000 + sink->lastFrameTime.tv_usec + frameDurationMsec * 1000; sink->lastFrameTime.tv_usec = requiredUsec % 1000000; sink->lastFrameTime.tv_sec = requiredUsec / 1000000; } } else { gettimeofday(&sink->lastFrameTime, NULL); } } else { gettimeofday(&sink->lastFrameTime, NULL); } reset_streams(frame); return 1; }
static void fss_frame_displayed(void* data, const FrameInfo* frameInfo) { FrameSequenceSink* sequence = (FrameSequenceSink*)data; msl_frame_displayed(sequence->switchListener, frameInfo); }
static int display_frame(X11XVDisplaySink* sink, X11DisplayFrame* frame, const FrameInfo* frameInfo) { struct timeval timeNow; long requiredUsec; long durationSlept; unsigned int windowWidth; unsigned int windowHeight; float scaleFactorX; float scaleFactorY; float scaleFactor; YUV_frame inputFrame; YUV_frame outputFrame; unsigned char* activeBuffer; int frameDurationMsec; int frameSlippage; frameDurationMsec = (int)(1000 * frameInfo->frameRate.den / (double)(frameInfo->frameRate.num)); frameSlippage = frameDurationMsec * 1000 / 2; /* half a frame */ if (frame->videoIsPresent) { /* convert if required */ if (sink->inputVideoFormat == UYVY_10BIT_FORMAT) { if (sink->swScale != 1) { /* scale required afterwards */ activeBuffer = frame->scaleInputBuffer; } else { /* no scale afterwards */ activeBuffer = (unsigned char*)frame->yuv_image->data; } ConvertFrameV210to8(activeBuffer, frame->inputBuffer, sink->inputWidth * 2, (sink->inputWidth + 47) / 48 * 128, sink->inputWidth, sink->inputHeight); } else if (sink->inputVideoFormat == YUV444_FORMAT) { if (sink->swScale != 1) { /* scale required afterwards */ activeBuffer = frame->scaleInputBuffer; } else { /* no scale afterwards */ activeBuffer = (unsigned char*)frame->yuv_image->data; } yuv444_to_uyvy(sink->inputWidth, sink->inputHeight, frame->inputBuffer, activeBuffer); } else if (sink->inputVideoFormat == YUV422_FORMAT) { if (sink->swScale != 1) { /* scale required afterwards */ activeBuffer = frame->scaleInputBuffer; } else { /* no scale afterwards */ activeBuffer = (unsigned char*)frame->yuv_image->data; } yuv422_to_uyvy_2(sink->inputWidth, sink->inputHeight, 0, frame->inputBuffer, activeBuffer); } else if (sink->inputVideoFormat == YUV422_10BIT_FORMAT) { if (sink->swScale != 1) { /* scale required afterwards */ activeBuffer = frame->scaleInputBuffer; } else { /* no scale afterwards */ activeBuffer = (unsigned char*)frame->yuv_image->data; } ConvertFrameYUV10to8_2(frame->ditherOutputBuffer, (const uint16_t*)frame->inputBuffer, sink->inputWidth, sink->inputHeight, 2, 1); yuv422_to_uyvy_2(sink->inputWidth, sink->inputHeight, 0, frame->ditherOutputBuffer, activeBuffer); } else if (sink->inputVideoFormat == YUV420_10BIT_FORMAT) { if (sink->swScale != 1) { /* scale required afterwards */ activeBuffer = frame->scaleInputBuffer; } else { /* no scale afterwards */ activeBuffer = (unsigned char*)frame->yuv_image->data; } ConvertFrameYUV10to8_2(activeBuffer, (const uint16_t*)frame->inputBuffer, sink->inputWidth, sink->inputHeight, 2, 2); } else { /* no conversion - scale input frame->input buffer != frame->yuv_image->data */ activeBuffer = frame->inputBuffer; } /* scale image and output to frame->yuv_image */ if (sink->swScale != 1) { YUV_frame_from_buffer(&inputFrame, (void*)activeBuffer, sink->inputWidth, sink->inputHeight, sink->outputYUVFormat); YUV_frame_from_buffer(&outputFrame, (void*)(unsigned char*)frame->yuv_image->data, sink->width, sink->height, sink->outputYUVFormat); small_pic(&inputFrame, &outputFrame, 0, 0, sink->swScale, sink->swScale, 1, sink->applyScaleFilter, sink->applyScaleFilter, frame->scaleWorkspace); } /* add OSD to frame */ if (sink->osd != NULL && sink->osdInitialised) { if (!osd_add_to_image(sink->osd, frameInfo, (unsigned char*)frame->yuv_image->data, frame->yuv_image->width, frame->yuv_image->height)) { ml_log_error("Failed to add OSD to frame\n"); /* continue anyway */ } } /* wait until it is time to display this frame */ gettimeofday(&timeNow, NULL); durationSlept = 0; if (frameInfo->rateControl) { durationSlept = sleep_diff(frameDurationMsec * 1000, &timeNow, &sink->lastFrameTime); } /* adjust the display width/height if the window has been resized */ windowWidth = sink->x11Common.windowWidth; windowHeight = sink->x11Common.windowHeight; scaleFactorX = windowWidth / (float)(sink->initialDisplayWidth); scaleFactorY = windowHeight / (float)(sink->initialDisplayHeight); scaleFactor = (scaleFactorX < scaleFactorY) ? scaleFactorX : scaleFactorY; sink->x11Common.displayWidth = sink->initialDisplayWidth * scaleFactor; sink->x11Common.displayHeight = sink->initialDisplayHeight * scaleFactor; XLockDisplay(sink->x11Common.windowInfo.display); if (sink->useSharedMemory) { XvShmPutImage(sink->x11Common.windowInfo.display, sink->xvport, sink->x11Common.windowInfo.window, sink->x11Common.windowInfo.gc, frame->yuv_image, 0, 0, frame->yuv_image->width, frame->yuv_image->height, 0, 0, sink->x11Common.displayWidth, sink->x11Common.displayHeight, False); } else { XvPutImage(sink->x11Common.windowInfo.display, sink->xvport, sink->x11Common.windowInfo.window, sink->x11Common.windowInfo.gc, frame->yuv_image, 0, 0, frame->yuv_image->width, frame->yuv_image->height, 0, 0, sink->x11Common.displayWidth, sink->x11Common.displayHeight); } XSync(sink->x11Common.windowInfo.display, False); XUnlockDisplay(sink->x11Common.windowInfo.display); x11c_process_events(&sink->x11Common); /* report that a new frame has been displayed */ msl_frame_displayed(sink->listener, frameInfo); /* set the time that this frame was displayed */ if (frameInfo->rateControl) { if (durationSlept < - frameSlippage) { /* reset rate control when slipped by more than frameSlippage */ sink->lastFrameTime = timeNow; } else { /* set what the frame's display time should have been */ requiredUsec = sink->lastFrameTime.tv_sec * 1000000 + sink->lastFrameTime.tv_usec + frameDurationMsec * 1000; sink->lastFrameTime.tv_usec = requiredUsec % 1000000; sink->lastFrameTime.tv_sec = requiredUsec / 1000000; } } else { gettimeofday(&sink->lastFrameTime, NULL); } } else { gettimeofday(&sink->lastFrameTime, NULL); } reset_streams(frame); return 1; }