SDL_UpdateYUVTexture to SDL_PIXELFORMAT_UYVY format

Dear All,

I am playing with SDL in android, and is it meaningful to display Texture of pixel format SDL_PIXELFORMAT_UYVY , with SDL_UpdateYUVTexture ?

Following is my Pseudo Code.

  1. Window

screen = SDL_CreateWindow (“Test ffmpeg”,SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 1280, 720, SDL_WINDOW_SHOWN|SDL_WINDOW_ALLOW_HIGHDPI );

  1. Context to convert native pixel format to PIX_FMT_UYVY422

pSwsCtx = sws_getContext (1280, 720, pCodecCtx->pix_fmt, 1280, 720, PIX_FMT_UYVY422, SWS_BICUBIC, NULL, NULL, NULL);

  1. Texture with SDL_PIXELFORMAT_UYVY

bmp = SDL_CreateTexture (renderer, SDL_PIXELFORMAT_UYVY, SDL_TEXTUREACCESS_STREAMING,1280, 720);

  1. For each Frame,

                           avpicture_fill((AVPicture *)pFrameUYVY422, picture_buf_yuv, PIX_FMT_YUV420P, 1280,720);
                            sws_scale(pSwsCtx, (const uint8_t * const *) pFrame->data,
                                           pFrame->linesize, 0, pCodecCtx->height, pFrameUYVY422->data,
                                             pFrameUYVY422->linesize);
    
                                SDL_UpdateYUVTexture(bmp, NULL, pFrameUYVY422->data[0], pFrameUYVY422->linesize[0], pFrameUYVY422->data[1], pFrameUYVY422->linesize[1], pFrameUYVY422->data[2], pFrameUYVY422->linesize[2]);
    
  2. Handle SDL Event

  3. Render Copy, and RenderPresent.

  4. Repeat to (4).

I am playing with SDL in android, and is it meaningful to display Texture
of pixel format SDL_PIXELFORMAT_UYVY , with SDL_UpdateYUVTexture ?

Why do u have to convert a YUV420P to a UYVY if SDL can display YUV420P
(aka YV12) without conversion?

Also you DO NOT need to scale a texture, texture have a “free” scale when
you “copy” them to the screen with SDL_RenderCopy()

I’ll try to show you these changes in your pseudocode:

Following is my Pseudo Code.

  1. Window

screen = SDL_CreateWindow (“Test ffmpeg”,SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED, 1280, 720,
SDL_WINDOW_SHOWN|SDL_WINDOW_ALLOW_HIGHDPI );

OK

  1. Context to convert native pixel format to PIX_FMT_UYVY422

pSwsCtx = sws_getContext (1280, 720, pCodecCtx->pix_fmt, 1280, 720,
PIX_FMT_UYVY422, SWS_BICUBIC, NULL, NULL, NULL);

This step is not needed.

  1. Texture with SDL_PIXELFORMAT_UYVY

bmp = SDL_CreateTexture (renderer, SDL_PIXELFORMAT_UYVY,
SDL_TEXTUREACCESS_STREAMING,1280, 720);

Do not allocate texture in advance, and, when you do it se
SDL_PIXELFORMAT_YV12 and SDL_TEXTUREACCESS_STATIC (you do not need
streaming access if you update textures through SDL_Update(YUV)Texture).

  1. For each Frame,

if (!bmp || ctx_->width != width_ || ctx_->height != height_) {
if (bmp)
SDL_DestroyTexture(bmp);

    bmp = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_YV12,

SDL_TEXTUREACCESS_STATIC, ctx_->width , ctx_->height);
[… add error check …]
}

Replace pFrameUYVY422 with picture_buf_yuv in the following line:

SDL_UpdateYUVTexture(bmp, NULL, pFrameUYVY422->data[0],
pFrameUYVY422->linesize[0], pFrameUYVY422->data[1],
pFrameUYVY422->linesize[1], pFrameUYVY422->data[2],
pFrameUYVY422->linesize[2]);

  1. Handle SDL Event

  2. Render Copy, and RenderPresent.

In RenderCopy use 0,0 1280x720 in dstrect (to get the free scale)>

  1. Repeat to (4).


Bye,
Gabry

Thanks Gabry. Few thinks i couldn’t understand.

  1. The pixel format that the device sends is UYVY, and i am displaying in YU12 texture, the images are displayed, but i see the frame gets light yellow color background altogether. [ ie; whitening , if i am right. ]

  2. I tried with Texture of type UIYUV, but still i see the yellow color whitening.

Here is the code:

in main ()
{

screen = SDL_CreateWindow (“Test ffmpeg”,SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 1280, 720,
SDL_WINDOW_SHOWN|SDL_WINDOW_ALLOW_HIGHDPI );

    renderer = SDL_CreateRenderer (screen, -1, SDL_RENDERER_ACCELERATED| SDL_RENDERER_TARGETTEXTURE);
    bmp = SDL_CreateTexture  (renderer, SDL_PIXELFORMAT_YV12, SDL_TEXTUREACCESS_STATIC,1280, 720);
 
    while (av_read_frame(pFormatCtx, &packet) >= 0) {
            if (packet.stream_index == videoStream) {
                    avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packet);

                    if (frameFinished) {
                            SDL_DestroyTexture (bmp);
                            bmp = SDL_CreateTexture  (renderer, SDL_PIXELFORMAT_YV12, SDL_TEXTUREACCESS_STATIC,1280, 720);
                            SDL_UpdateYUVTexture(bmp, NULL, pFrame->data[0], pFrame->linesize[0], pFrame->data[1], pFrame->linesize[1],  pFrame->data[2], pFrame->linesize[2]);

                    }
            }

     
          SDL_RenderClear ();
           SDL_RenderCopy(renderer, bmp, NULL, NULL);
            SDL_RenderPresent(renderer);

            // SDL Event Handling
            .......
           ........
            }

    av_free(pFrame);
    avcodec_close(pCodecCtx);
    avformat_close_input(&pFormatCtx);

}

Thanks Gabry. Few thinks i couldn’t understand.

  1. The pixel format that the device sends is UYVY, and i am displaying in
    YU12 texture, the images are displayed, but i see the frame gets light
    yellow color background altogether. [ ie; whitening , if i am right. ]

Try to allocate your context somewhat like this:

ctx_ = avcodec_alloc_context3(codec);
ctx_->width = 0;
ctx_->height = 0;
ctx_->pix_fmt = PIX_FMT_YUV420P;

In this way avcodec will ensure the output format is something you can
display easily.

SDL_DestroyTexture (bmp);

bmp = SDL_CreateTexture (renderer, SDL_PIXELFORMAT_YV12,
SDL_TEXTUREACCESS_STATIC,1280, 720);

Your texture should have the size of the frame decoded by avcodec
(pCodecCtx->width, pCodecCtx->height), not a static value. Also there is no
need to destroy and recreate the texture every frame, do it only if you
detect that the frame size is changed.On Wed, Feb 19, 2014 at 7:36 AM, keestu wrote:


Bye,
Gabry