Welcome!

Welcome to the official BlackBerry Support Community Forums.

This is your resource to discuss support topics with your peers, and learn from each other.

inside custom component

Native Development

Reply
Developer
danielleCoder
Posts: 178
Registered: ‎04-16-2011
My Device: torch 9800

Displaying AVFrame

I am having problems displaying the contents of a correctly decoded ffmpeg AVFrame.

 

When I try to follow previous threads about ffmpeg I get a sigsegv failure when memcpy is called on the U or V part of the YUV data. If I comment out the UV memcpy and only have memcpy for Y I get half a video on screen!

 

The video is coming from a http stream and is mp4.

 

 

 uint8_t *srcy = pic->data[0];
                        uint8_t *srcu = pic->data[1];
                        uint8_t *srcv = pic->data[2];
                        
                        unsigned char *ptr = NULL;
                        screen_get_buffer_property_pv(mScreenPixelBuffer, SCREEN_PROPERTY_POINTER, (void**) &ptr);
                        unsigned char *y = ptr;
                        unsigned char *u = y + (pic->height * mStride);
                        unsigned char *v = u + (pic->height * mStride) / 4;
                        int i = 0;
                       
                        for ( i = 0; i < pic->height; i++)
                        {
                            int doff = i * mStride;
                            int soff = i * pic->linesize[0];
                            memcpy(&y[doff], &srcy[soff], pic->width);
                        }

                        for ( i = 0; i < pic->height / 2; i++)
                        {
                            int doff = i * mStride / 2;
                            int soff = i * pic->linesize[1];
                  //fails here          memcpy(&u[doff], &srcu[soff], pic->width / 2);
                        }

                        for ( i = 0; i < pic->height / 2; i++)
                        {
                            int doff = i * mStride / 2;
                            int soff = i * pic->linesize[2];
                 //fails here           memcpy(&v[doff], &srcv[soff], pic->width / 2);
                        }

 

 

 

BlackBerry Development Advisor
smcveigh
Posts: 668
Registered: ‎11-29-2011
My Device: developer

Re: Displaying AVFrame

It looks like you are assuming your destination buffer is in YUV420P format.

I do not believe screen supports YUV420P.  What format did you ask for when you created the screen buffer?

Where are you getting mStride from, out of curiosity?

 

In any event, you likely need to convert your YUV420P data to NV12, which means you will need to interleave the U and V planes into the semi-planar UV plane that NV12 implements.

 

eg. on this 4x4 YUV420P buffer, you need to translate from this:

YYYY

YYYY

YYYY

YYYY

UU

UU

VV

VV

 

to this (in NV12 space):

YYYY

YYYY

YYYY

YYYY

UVUV

UVUV

 

I'll leave the mechanics as an exercise to the reader :smileyhappy:

 

BEWARE!

 

On some platforms, the UV plane does not immediately follow the Y plane in memory, but is offset by a certain amount.  You can query the SCREEN_PROPERTY_PLANAR_OFFSETS to determine where in memory the Y and UV planes start (usually 0 and stride*height padded to some alignment value).

 

The next BEWARE, is that on some platforms, the stride may also differ between the Y plane and the UV plane, although this may only happen in specific video coding examples due to some hardware-specific requirements.  I do not yet have a good solution for how to query what the different strides are.  As far as I know, you can only query the primary (Y) stride by checking SCREEN_PROPERTY_STRIDE.  I will try to find out more though... I know I've asked for this functionality in the past.. maybe it got added.

 

Cheers,

Sean

Developer
danielleCoder
Posts: 178
Registered: ‎04-16-2011
My Device: torch 9800

Re: Displaying AVFrame

Thanks Sean,

 

Got the frame displayed by setting screen_set_pixmap_property_iv to use yuv format.

 

I thought I'd tried setting this before creating this thread but just went back to problem and realised I actually hadn't.