LCOV - code coverage report
Current view: top level - libavcodec - v4l2_m2m_dec.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 84 0.0 %
Date: 2017-12-15 18:13:28 Functions: 0 4 0.0 %

          Line data    Source code
       1             : /*
       2             :  * V4L2 mem2mem decoders
       3             :  *
       4             :  * Copyright (C) 2017 Alexis Ballier <aballier@gentoo.org>
       5             :  * Copyright (C) 2017 Jorge Ramirez <jorge.ramirez-ortiz@linaro.org>
       6             :  *
       7             :  * This file is part of FFmpeg.
       8             :  *
       9             :  * FFmpeg is free software; you can redistribute it and/or
      10             :  * modify it under the terms of the GNU Lesser General Public
      11             :  * License as published by the Free Software Foundation; either
      12             :  * version 2.1 of the License, or (at your option) any later version.
      13             :  *
      14             :  * FFmpeg is distributed in the hope that it will be useful,
      15             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      16             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      17             :  * Lesser General Public License for more details.
      18             :  *
      19             :  * You should have received a copy of the GNU Lesser General Public
      20             :  * License along with FFmpeg; if not, write to the Free Software
      21             :  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
      22             :  */
      23             : 
      24             : #include <linux/videodev2.h>
      25             : #include <sys/ioctl.h>
      26             : #include "libavutil/pixfmt.h"
      27             : #include "libavutil/pixdesc.h"
      28             : #include "libavutil/opt.h"
      29             : #include "libavcodec/avcodec.h"
      30             : #include "libavcodec/decode.h"
      31             : 
      32             : #include "v4l2_context.h"
      33             : #include "v4l2_m2m.h"
      34             : #include "v4l2_fmt.h"
      35             : 
      36           0 : static int v4l2_try_start(AVCodecContext *avctx)
      37             : {
      38           0 :     V4L2m2mContext *s = avctx->priv_data;
      39           0 :     V4L2Context *const capture = &s->capture;
      40           0 :     V4L2Context *const output = &s->output;
      41             :     struct v4l2_selection selection;
      42             :     int ret;
      43             : 
      44             :     /* 1. start the output process */
      45           0 :     if (!output->streamon) {
      46           0 :         ret = ff_v4l2_context_set_status(output, VIDIOC_STREAMON);
      47           0 :         if (ret < 0) {
      48           0 :             av_log(avctx, AV_LOG_DEBUG, "VIDIOC_STREAMON on output context\n");
      49           0 :             return ret;
      50             :         }
      51             :     }
      52             : 
      53           0 :     if (capture->streamon)
      54           0 :         return 0;
      55             : 
      56             :     /* 2. get the capture format */
      57           0 :     capture->format.type = capture->type;
      58           0 :     ret = ioctl(s->fd, VIDIOC_G_FMT, &capture->format);
      59           0 :     if (ret) {
      60           0 :         av_log(avctx, AV_LOG_WARNING, "VIDIOC_G_FMT ioctl\n");
      61           0 :         return ret;
      62             :     }
      63             : 
      64             :     /* 2.1 update the AVCodecContext */
      65           0 :     avctx->pix_fmt = ff_v4l2_format_v4l2_to_avfmt(capture->format.fmt.pix_mp.pixelformat, AV_CODEC_ID_RAWVIDEO);
      66           0 :     capture->av_pix_fmt = avctx->pix_fmt;
      67             : 
      68             :     /* 3. set the crop parameters */
      69           0 :     selection.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
      70           0 :     selection.r.height = avctx->coded_height;
      71           0 :     selection.r.width = avctx->coded_width;
      72           0 :     ret = ioctl(s->fd, VIDIOC_S_SELECTION, &selection);
      73           0 :     if (!ret) {
      74           0 :         ret = ioctl(s->fd, VIDIOC_G_SELECTION, &selection);
      75           0 :         if (ret) {
      76           0 :             av_log(avctx, AV_LOG_WARNING, "VIDIOC_G_SELECTION ioctl\n");
      77             :         } else {
      78           0 :             av_log(avctx, AV_LOG_DEBUG, "crop output %dx%d\n", selection.r.width, selection.r.height);
      79             :             /* update the size of the resulting frame */
      80           0 :             capture->height = selection.r.height;
      81           0 :             capture->width  = selection.r.width;
      82             :         }
      83             :     }
      84             : 
      85             :     /* 4. init the capture context now that we have the capture format */
      86           0 :     if (!capture->buffers) {
      87           0 :         ret = ff_v4l2_context_init(capture);
      88           0 :         if (ret) {
      89           0 :             av_log(avctx, AV_LOG_DEBUG, "can't request output buffers\n");
      90           0 :             return ret;
      91             :         }
      92             :     }
      93             : 
      94             :     /* 5. start the capture process */
      95           0 :     ret = ff_v4l2_context_set_status(capture, VIDIOC_STREAMON);
      96           0 :     if (ret) {
      97           0 :         av_log(avctx, AV_LOG_DEBUG, "VIDIOC_STREAMON, on capture context\n");
      98           0 :         return ret;
      99             :     }
     100             : 
     101           0 :     return 0;
     102             : }
     103             : 
     104           0 : static int v4l2_prepare_decoder(V4L2m2mContext *s)
     105             : {
     106             :     struct v4l2_event_subscription sub;
     107           0 :     V4L2Context *output = &s->output;
     108             :     int ret;
     109             : 
     110             :     /**
     111             :      * requirements
     112             :      */
     113           0 :     memset(&sub, 0, sizeof(sub));
     114           0 :     sub.type = V4L2_EVENT_SOURCE_CHANGE;
     115           0 :     ret = ioctl(s->fd, VIDIOC_SUBSCRIBE_EVENT, &sub);
     116           0 :     if ( ret < 0) {
     117           0 :         if (output->height == 0 || output->width == 0) {
     118           0 :             av_log(s->avctx, AV_LOG_ERROR,
     119             :                 "the v4l2 driver does not support VIDIOC_SUBSCRIBE_EVENT\n"
     120             :                 "you must provide codec_height and codec_width on input\n");
     121           0 :             return ret;
     122             :         }
     123             :     }
     124             : 
     125           0 :     return 0;
     126             : }
     127             : 
     128           0 : static int v4l2_receive_frame(AVCodecContext *avctx, AVFrame *frame)
     129             : {
     130           0 :     V4L2m2mContext *s = avctx->priv_data;
     131           0 :     V4L2Context *const capture = &s->capture;
     132           0 :     V4L2Context *const output = &s->output;
     133           0 :     AVPacket avpkt = {0};
     134             :     int ret;
     135             : 
     136           0 :     ret = ff_decode_get_packet(avctx, &avpkt);
     137           0 :     if (ret < 0 && ret != AVERROR_EOF)
     138           0 :         return ret;
     139             : 
     140           0 :     if (s->draining)
     141           0 :         goto dequeue;
     142             : 
     143           0 :     ret = ff_v4l2_context_enqueue_packet(output, &avpkt);
     144           0 :     if (ret < 0) {
     145           0 :         if (ret != AVERROR(ENOMEM))
     146           0 :            return ret;
     147             :         /* no input buffers available, continue dequeing */
     148             :     }
     149             : 
     150           0 :     if (avpkt.size) {
     151           0 :         ret = v4l2_try_start(avctx);
     152           0 :         if (ret)
     153           0 :             return 0;
     154             :     }
     155             : 
     156           0 : dequeue:
     157           0 :     return ff_v4l2_context_dequeue_frame(capture, frame);
     158             : }
     159             : 
     160           0 : static av_cold int v4l2_decode_init(AVCodecContext *avctx)
     161             : {
     162           0 :     V4L2m2mContext *s = avctx->priv_data;
     163           0 :     V4L2Context *capture = &s->capture;
     164           0 :     V4L2Context *output = &s->output;
     165             :     int ret;
     166             : 
     167             :     /* if these dimensions are invalid (ie, 0 or too small) an event will be raised
     168             :      * by the v4l2 driver; this event will trigger a full pipeline reconfig and
     169             :      * the proper values will be retrieved from the kernel driver.
     170             :      */
     171           0 :     output->height = capture->height = avctx->coded_height;
     172           0 :     output->width = capture->width = avctx->coded_width;
     173             : 
     174           0 :     output->av_codec_id = avctx->codec_id;
     175           0 :     output->av_pix_fmt  = AV_PIX_FMT_NONE;
     176             : 
     177           0 :     capture->av_codec_id = AV_CODEC_ID_RAWVIDEO;
     178           0 :     capture->av_pix_fmt = avctx->pix_fmt;
     179             : 
     180           0 :     ret = ff_v4l2_m2m_codec_init(avctx);
     181           0 :     if (ret) {
     182           0 :         av_log(avctx, AV_LOG_ERROR, "can't configure decoder\n");
     183           0 :         return ret;
     184             :     }
     185             : 
     186           0 :     return v4l2_prepare_decoder(s);
     187             : }
     188             : 
     189             : #define OFFSET(x) offsetof(V4L2m2mContext, x)
     190             : #define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM
     191             : 
     192             : static const AVOption options[] = {
     193             :     V4L_M2M_DEFAULT_OPTS,
     194             :     { "num_capture_buffers", "Number of buffers in the capture context",
     195             :         OFFSET(capture.num_buffers), AV_OPT_TYPE_INT, {.i64 = 20}, 20, INT_MAX, FLAGS },
     196             :     { NULL},
     197             : };
     198             : 
     199             : #define M2MDEC(NAME, LONGNAME, CODEC, bsf_name) \
     200             : static const AVClass v4l2_m2m_ ## NAME ## _dec_class = {\
     201             :     .class_name = #NAME "_v4l2_m2m_decoder",\
     202             :     .item_name  = av_default_item_name,\
     203             :     .option     = options,\
     204             :     .version    = LIBAVUTIL_VERSION_INT,\
     205             : };\
     206             : \
     207             : AVCodec ff_ ## NAME ## _v4l2m2m_decoder = { \
     208             :     .name           = #NAME "_v4l2m2m" ,\
     209             :     .long_name      = NULL_IF_CONFIG_SMALL("V4L2 mem2mem " LONGNAME " decoder wrapper"),\
     210             :     .type           = AVMEDIA_TYPE_VIDEO,\
     211             :     .id             = CODEC ,\
     212             :     .priv_data_size = sizeof(V4L2m2mContext),\
     213             :     .priv_class     = &v4l2_m2m_ ## NAME ## _dec_class,\
     214             :     .init           = v4l2_decode_init,\
     215             :     .receive_frame  = v4l2_receive_frame,\
     216             :     .close          = ff_v4l2_m2m_codec_end,\
     217             :     .bsfs           = bsf_name, \
     218             :     .capabilities   = AV_CODEC_CAP_HARDWARE, \
     219             :     .wrapper_name   = "v4l2m2m", \
     220             : };
     221             : 
     222             : M2MDEC(h264,  "H.264", AV_CODEC_ID_H264,       "h264_mp4toannexb");
     223             : M2MDEC(hevc,  "HEVC",  AV_CODEC_ID_HEVC,       "hevc_mp4toannexb");
     224             : M2MDEC(mpeg1, "MPEG1", AV_CODEC_ID_MPEG1VIDEO, NULL);
     225             : M2MDEC(mpeg2, "MPEG2", AV_CODEC_ID_MPEG2VIDEO, NULL);
     226             : M2MDEC(mpeg4, "MPEG4", AV_CODEC_ID_MPEG4,      NULL);
     227             : M2MDEC(h263,  "H.263", AV_CODEC_ID_H263,       NULL);
     228             : M2MDEC(vc1 ,  "VC1",   AV_CODEC_ID_VC1,        NULL);
     229             : M2MDEC(vp8,   "VP8",   AV_CODEC_ID_VP8,        NULL);
     230             : M2MDEC(vp9,   "VP9",   AV_CODEC_ID_VP9,        NULL);

Generated by: LCOV version 1.13