Example #1
0
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;
}
Example #2
0
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;
}