Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle nv12 pix fmt. #57

Open
topilski opened this issue Apr 16, 2017 · 5 comments
Open

Handle nv12 pix fmt. #57

topilski opened this issue Apr 16, 2017 · 5 comments

Comments

@topilski
Copy link

topilski commented Apr 16, 2017

Hi, according code https://github.com/linux-sunxi/libvdpau-sunxi/blob/master/decoder.c#L149 used VDP_YCBCR_FORMAT_YV12 pixformat for cedar version grather or equal 0x1680, but when executed https://github.com/linux-sunxi/libvdpau-sunxi/blob/master/surface_video.c#L160 not handled case when vs->source_format == VDP_YCBCR_FORMAT_NV12 only handled for old cedar library https://github.com/linux-sunxi/libvdpau-sunxi/blob/master/surface_video.c#L208 , why nv12 for new cedar library are not work out? Also wiil be cool have conversion copy_yv12_to_nv12 and veca versa.

static INLINE void
u_copy_nv12_to_yv12(void *const *destination_data,
                    uint32_t const *destination_pitches,
                    int src_plane, int src_field,
                    int src_stride, int num_fields,
                    uint8_t const *src,
                    int width, int height)
{
   int x, y;
   unsigned u_stride = destination_pitches[2] * num_fields;
   unsigned v_stride = destination_pitches[1] * num_fields;
   uint8_t *u_dst = (uint8_t *)destination_data[2] + destination_pitches[2] * src_field;
   uint8_t *v_dst = (uint8_t *)destination_data[1] + destination_pitches[1] * src_field;

   /* TODO: SIMD */
   for (y = 0; y < height; y++) {
      for (x = 0; x < width; x++) {
         u_dst[x] = src[2*x];
         v_dst[x] = src[2*x+1];
      }
      u_dst += u_stride;
      v_dst += v_stride;
      src += src_stride;
   }
}

static INLINE void
u_copy_yv12_to_nv12(void *const *destination_data,
                    uint32_t const *destination_pitches,
                    int src_plane, int src_field,
                    int src_stride, int num_fields,
                    uint8_t const *src,
                    int width, int height)
{
   int x, y;
   unsigned offset = 2 - src_plane;
   unsigned stride = destination_pitches[1] * num_fields;
   uint8_t *dst = (uint8_t *)destination_data[1] + destination_pitches[1] * src_field;

   /* TODO: SIMD */
   for (y = 0; y < height; y++) {
      for (x = 0; x < 2 * width; x += 2) {
         dst[x+offset] = src[x>>1];
      }
      dst += stride;
      src += src_stride;
   }
}
@rellla
Copy link
Member

rellla commented Apr 18, 2017

Because nobody implemented the get_bits_ycbcr case, if you want to get NV12 from the decoder's YV12 surface.

vs->source_format == VDP_YCBCR_FORMAT_YV12 && destination_ycbcr_format == VDP_YCBCR_FORMAT_NV12

is simply not implemented. We have more than just YV12 and NV12 that should be implemented according to the API: http://http.download.nvidia.com/XFree86/vdpau/doxygen/html/group__misc__types.html#gab7550cf65e6d46f4fd7a1e322372e207

Feel free to do a pull request ;)

@topilski
Copy link
Author

topilski commented Apr 18, 2017

Hi @rellla i with pleasure will be implement this functionality but i don't understand how convert your pointers src = cedrus_mem_get_pointer(vs->yuv->data); dst = destination_data[0]; into common yv12 to nv12 conversion algorithm.

@rellla
Copy link
Member

rellla commented Apr 18, 2017

I have not read up about this algorithm, but cedrus_mem_get_pointer(vs->yuv->data) will return a pointer to the beginning of the yuv bitstream, which you can use with CPU. destination_data[0] points to the beginning of the first plane (depending on the output format)
http://http.download.nvidia.com/XFree86/vdpau/doxygen/html/group___vdp_video_surface.html#gae3550dc62e4e4c390c1874b37f96e7c0
For the planes, check https://wiki.videolan.org/YUV/

This is YV12 (for 1 pixel)
YYYYYYYY UU VV (3 planes)
NV12 (for 1 pixel)
YYYYYYYY UVUV

which means, when converting NV12 to YV12 you just need to split up cedrus_mem_get_pointer(vs->yuv->data)+ vs->luma_size into separate U (destination_data[1]) and V (destination_data[2]) planes.

This is, what basically tiled_deinterleave_to_planar does - but without doing it with the tiled input ....
Where did the above code snippets come from?

@topilski
Copy link
Author

@rellla
Copy link
Member

rellla commented Apr 18, 2017

just asked because of the license ...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants