[FFmpeg-devel] [PATCHv6 4/4] libavcodec: v4l2: add support for v4l2 mem2mem codecs

Mark Thompson sw at jkqxz.net
Mon Aug 28 13:23:25 EEST 2017


On 27/08/17 20:41, Jorge Ramirez wrote:
> On 08/27/2017 09:09 PM, Jorge Ramirez wrote:
>> On 08/25/2017 05:35 PM, wm4 wrote:
>>>> +static int buffer_ops_v4l2buf_to_avframe(AVFrame *frame, V4L2Buffer *avbuf)
>>>> +{
>>>> +    int i, ret;
>>>> +
>>>> +    av_frame_unref(frame);
>>>> +
>>>> +    /* 1. get references to the actual data */
>>>> +    for (i = 0; i < avbuf->num_planes; i++) {
>>>> +        ret = avbuf->ops.buf_to_bufref(avbuf, i, &frame->buf[i]);
>>>> +        if (ret)
>>>> +            return ret;
>>>> +
>>>> +        frame->linesize[i] = avbuf->bytesperline[i];
>>>> +        frame->data[i] = frame->buf[i]->data;
>>>> +    }
>>>> +
>>>> +    /* 1.1 fixup special cases */
>>>> +    switch (avbuf->context->av_pix_fmt) {
>>>> +    case AV_PIX_FMT_NV12:
>>>> +        if (avbuf->num_planes > 1)
>>>> +            break;
>>>> +        frame->linesize[1] = avbuf->bytesperline[0];
>>>> +        frame->data[1] = frame->buf[0]->data + avbuf->bytesperline[0] * avbuf->context->format.fmt.pix_mp.height;
>>>> +        break;
>>>> +    default:
>>>> +        break;
>>>> +    }
>>>> +
>>>> +    /* 2. get frame information */
>>>> +    frame->key_frame = !!(avbuf->buf.flags & V4L2_BUF_FLAG_KEYFRAME);
>>>> +    frame->format = avbuf->context->av_pix_fmt;
>>>> +
>>>> +    /* these values are updated also during re-init in process_video_event */
>>>> +    frame->height = avbuf->context->height;
>>>> +    frame->width = avbuf->context->width;
>>>> +    frame->pts = get_pts(avbuf);
>>>> +
>>>> +    /* 3. report errors upstream */
>>>> +    if (avbuf->buf.flags & V4L2_BUF_FLAG_ERROR) {
>>>> +        av_log(avbuf->context->log_ctx, AV_LOG_ERROR, "%s: driver decode error\n", avbuf->context->name);
>>>> +        frame->decode_error_flags |= FF_DECODE_ERROR_INVALID_BITSTREAM;
>>>> +    }
>>>> +
>>>> +    return 0;
>>>> +}
>>> This function seems to lack setting typically required metadata like
>>> colorspace.
>>>
>>
>> ok I will retrieve the colorspace from the v4l2 format structure and set it in the frame.
> 
> um, I dont see a 1:1 mapping between the colorspaces reported from v4l2 and what ffmpeg expects (I am also not a subject matter expert on this :( ).
> 
> Could I get some guidance on the translation table below please?
> btw in my simple tests - ffplay decoded vp8, vp9, mpeg4, mpeg2, h263, h264 and hevc I didnt need this field so I am not sure if I am getting it right.
> 
> TIA
> 
> static inline enum AVColorSpace get_colorspace(V4L2Buffer *buf)
> {
>     enum v4l2_colorspace cs;
> 
>     cs = V4L2_TYPE_IS_MULTIPLANAR(buf->context->type) ?
>         buf->context->format.fmt.pix_mp.colorspace :
>         buf->context->format.fmt.pix.colorspace;
> 
>     /* */
>     switch (cs) {
>     case V4L2_COLORSPACE_SMPTE170M: return AVCOL_SPC_SMPTE170M;
>     case V4L2_COLORSPACE_SMPTE240M: return AVCOL_SPC_SMPTE240M;
>     case V4L2_COLORSPACE_470_SYSTEM_BG: return AVCOL_SPC_BT470BG;
>     case V4L2_COLORSPACE_BT2020: return AVCOL_SPC_BT2020_CL;
>     case V4L2_COLORSPACE_REC709: return AVCOL_SPC_BT709;
>     case V4L2_COLORSPACE_ADOBERGB:
>     case V4L2_COLORSPACE_SRGB:
>     case V4L2_COLORSPACE_DCI_P3:
>     case V4L2_COLORSPACE_JPEG:
>     case V4L2_COLORSPACE_RAW:
>     default:
>         return AVCOL_SPC_RGB;
>     }
> }

The ffmpeg enums use the same ISO 11664-1 values as H.264, H.265 and MPEG-2 do.  Since there must be code in your V4L2 driver to translate the V4L2 enums both to and from that (for encode and decode respectively), I suggest just copying the logic of that code to do the matching opposite direction on the ffmpeg side.  (Look for code reading/writing colour_primaries, transfer_characteristics and matrix_coefficients in the VUI section of the SPS.)

- Mark


More information about the ffmpeg-devel mailing list