LCOV - code coverage report
Current view: top level - libavcodec - smvjpegdec.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 80 103 77.7 %
Date: 2017-12-17 04:34:43 Functions: 5 5 100.0 %

          Line data    Source code
       1             : /*
       2             :  * SMV JPEG decoder
       3             :  * Copyright (c) 2013 Ash Hughes
       4             :  *
       5             :  * This file is part of FFmpeg.
       6             :  *
       7             :  * FFmpeg is free software; you can redistribute it and/or
       8             :  * modify it under the terms of the GNU Lesser General Public
       9             :  * License as published by the Free Software Foundation; either
      10             :  * version 2.1 of the License, or (at your option) any later version.
      11             :  *
      12             :  * FFmpeg is distributed in the hope that it will be useful,
      13             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      15             :  * Lesser General Public License for more details.
      16             :  *
      17             :  * You should have received a copy of the GNU Lesser General Public
      18             :  * License along with FFmpeg; if not, write to the Free Software
      19             :  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
      20             :  */
      21             : 
      22             : /**
      23             :  * @file
      24             :  * SMV JPEG decoder.
      25             :  */
      26             : 
      27             : // #define DEBUG
      28             : #include "avcodec.h"
      29             : #include "libavutil/opt.h"
      30             : #include "libavutil/imgutils.h"
      31             : #include "mjpegdec.h"
      32             : #include "internal.h"
      33             : 
      34             : typedef struct SMVJpegDecodeContext {
      35             :     MJpegDecodeContext jpg;
      36             :     AVFrame *picture[2]; /* pictures array */
      37             :     AVCodecContext* avctx;
      38             :     int frames_per_jpeg;
      39             :     int mjpeg_data_size;
      40             : } SMVJpegDecodeContext;
      41             : 
      42          39 : static inline void smv_img_pnt_plane(uint8_t      **dst, uint8_t *src,
      43             :                                      int src_linesize, int height, int nlines)
      44             : {
      45          39 :     if (!dst || !src)
      46           0 :         return;
      47          39 :     src += (nlines) * src_linesize * height;
      48          39 :     *dst = src;
      49             : }
      50             : 
      51          13 : static inline void smv_img_pnt(uint8_t *dst_data[4], uint8_t *src_data[4],
      52             :                                const int src_linesizes[4],
      53             :                                enum AVPixelFormat pix_fmt, int width, int height,
      54             :                                int nlines)
      55             : {
      56          13 :     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt);
      57          13 :     int i, planes_nb = 0;
      58             : 
      59          13 :     if (desc->flags & AV_PIX_FMT_FLAG_HWACCEL)
      60           0 :         return;
      61             : 
      62          52 :     for (i = 0; i < desc->nb_components; i++)
      63          39 :         planes_nb = FFMAX(planes_nb, desc->comp[i].plane + 1);
      64             : 
      65          52 :     for (i = 0; i < planes_nb; i++) {
      66          39 :         int h = height;
      67          39 :         if (i == 1 || i == 2) {
      68          26 :             h = AV_CEIL_RSHIFT(height, desc->log2_chroma_h);
      69             :         }
      70          39 :         smv_img_pnt_plane(&dst_data[i], src_data[i],
      71          39 :             src_linesizes[i], h, nlines);
      72             :     }
      73          26 :     if (desc->flags & AV_PIX_FMT_FLAG_PAL ||
      74          13 :         desc->flags & AV_PIX_FMT_FLAG_PSEUDOPAL)
      75           0 :         dst_data[1] = src_data[1];
      76             : }
      77             : 
      78           2 : static av_cold int smvjpeg_decode_end(AVCodecContext *avctx)
      79             : {
      80           2 :     SMVJpegDecodeContext *s = avctx->priv_data;
      81           2 :     MJpegDecodeContext *jpg = &s->jpg;
      82             :     int ret;
      83             : 
      84           2 :     jpg->picture_ptr = NULL;
      85           2 :     av_frame_free(&s->picture[0]);
      86           2 :     av_frame_free(&s->picture[1]);
      87           2 :     ret = avcodec_close(s->avctx);
      88           2 :     av_freep(&s->avctx);
      89           2 :     return ret;
      90             : }
      91             : 
      92           2 : static av_cold int smvjpeg_decode_init(AVCodecContext *avctx)
      93             : {
      94           2 :     SMVJpegDecodeContext *s = avctx->priv_data;
      95             :     AVCodec *codec;
      96           2 :     AVDictionary *thread_opt = NULL;
      97           2 :     int ret = 0, r;
      98             : 
      99           2 :     s->frames_per_jpeg = 0;
     100             : 
     101           2 :     s->picture[0] = av_frame_alloc();
     102           2 :     if (!s->picture[0])
     103           0 :         return AVERROR(ENOMEM);
     104             : 
     105           2 :     s->picture[1] = av_frame_alloc();
     106           2 :     if (!s->picture[1]) {
     107           0 :         av_frame_free(&s->picture[0]);
     108           0 :         return AVERROR(ENOMEM);
     109             :     }
     110             : 
     111           2 :     s->jpg.picture_ptr      = s->picture[0];
     112             : 
     113           2 :     if (avctx->extradata_size >= 4)
     114           2 :         s->frames_per_jpeg = AV_RL32(avctx->extradata);
     115             : 
     116           2 :     if (s->frames_per_jpeg <= 0) {
     117           0 :         av_log(avctx, AV_LOG_ERROR, "Invalid number of frames per jpeg.\n");
     118           0 :         ret = AVERROR_INVALIDDATA;
     119             :     }
     120             : 
     121           2 :     codec = avcodec_find_decoder(AV_CODEC_ID_MJPEG);
     122           2 :     if (!codec) {
     123           0 :         av_log(avctx, AV_LOG_ERROR, "MJPEG codec not found\n");
     124           0 :         smvjpeg_decode_end(avctx);
     125           0 :         return AVERROR_DECODER_NOT_FOUND;
     126             :     }
     127             : 
     128           2 :     s->avctx = avcodec_alloc_context3(codec);
     129             : 
     130           2 :     av_dict_set(&thread_opt, "threads", "1", 0);
     131           2 :     s->avctx->refcounted_frames = 1;
     132           2 :     s->avctx->flags = avctx->flags;
     133           2 :     s->avctx->idct_algo = avctx->idct_algo;
     134           2 :     if ((r = ff_codec_open2_recursive(s->avctx, codec, &thread_opt)) < 0) {
     135           0 :         av_log(avctx, AV_LOG_ERROR, "MJPEG codec failed to open\n");
     136           0 :         ret = r;
     137             :     }
     138           2 :     av_dict_free(&thread_opt);
     139             : 
     140           2 :     if (ret < 0)
     141           0 :         smvjpeg_decode_end(avctx);
     142           2 :     return ret;
     143             : }
     144             : 
     145          13 : static int smvjpeg_decode_frame(AVCodecContext *avctx, void *data, int *data_size,
     146             :                             AVPacket *avpkt)
     147             : {
     148             :     const AVPixFmtDescriptor *desc;
     149          13 :     SMVJpegDecodeContext *s = avctx->priv_data;
     150          13 :     AVFrame* mjpeg_data = s->picture[0];
     151          13 :     int i, cur_frame = 0, ret = 0;
     152             : 
     153          13 :     cur_frame = avpkt->pts % s->frames_per_jpeg;
     154             : 
     155             :     /* cur_frame is later used to calculate the buffer offset, so it mustn't be negative */
     156          13 :     if (cur_frame < 0)
     157           0 :         cur_frame += s->frames_per_jpeg;
     158             : 
     159             :     /* Are we at the start of a block? */
     160          13 :     if (!cur_frame) {
     161           3 :         av_frame_unref(mjpeg_data);
     162           3 :         ret = avcodec_decode_video2(s->avctx, mjpeg_data, &s->mjpeg_data_size, avpkt);
     163           3 :         if (ret < 0) {
     164           0 :             s->mjpeg_data_size = 0;
     165           0 :             return ret;
     166             :         }
     167          10 :     } else if (!s->mjpeg_data_size)
     168           0 :         return AVERROR(EINVAL);
     169             : 
     170          13 :     desc = av_pix_fmt_desc_get(s->avctx->pix_fmt);
     171          13 :     av_assert0(desc);
     172             : 
     173          13 :     if (mjpeg_data->height % (s->frames_per_jpeg << desc->log2_chroma_h)) {
     174           0 :         av_log(avctx, AV_LOG_ERROR, "Invalid height\n");
     175           0 :         return AVERROR_INVALIDDATA;
     176             :     }
     177             : 
     178             :     /*use the last lot... */
     179          13 :     *data_size = s->mjpeg_data_size;
     180             : 
     181          13 :     avctx->pix_fmt = s->avctx->pix_fmt;
     182             : 
     183             :     /* We shouldn't get here if frames_per_jpeg <= 0 because this was rejected
     184             :        in init */
     185          13 :     ret = ff_set_dimensions(avctx, mjpeg_data->width, mjpeg_data->height / s->frames_per_jpeg);
     186          13 :     if (ret < 0) {
     187           0 :         av_log(s, AV_LOG_ERROR, "Failed to set dimensions\n");
     188           0 :         return ret;
     189             :     }
     190             : 
     191          13 :     if (*data_size) {
     192          13 :         s->picture[1]->extended_data = NULL;
     193          13 :         s->picture[1]->width         = avctx->width;
     194          13 :         s->picture[1]->height        = avctx->height;
     195          13 :         s->picture[1]->format        = avctx->pix_fmt;
     196             :         /* ff_init_buffer_info(avctx, &s->picture[1]); */
     197          13 :         smv_img_pnt(s->picture[1]->data, mjpeg_data->data, mjpeg_data->linesize,
     198             :                     avctx->pix_fmt, avctx->width, avctx->height, cur_frame);
     199         117 :         for (i = 0; i < AV_NUM_DATA_POINTERS; i++)
     200         104 :             s->picture[1]->linesize[i] = mjpeg_data->linesize[i];
     201             : 
     202          13 :         ret = av_frame_ref(data, s->picture[1]);
     203          13 :         if (ret < 0)
     204           0 :             return ret;
     205             :     }
     206             : 
     207          13 :     return avpkt->size;
     208             : }
     209             : 
     210             : static const AVClass smvjpegdec_class = {
     211             :     .class_name = "SMVJPEG decoder",
     212             :     .item_name  = av_default_item_name,
     213             :     .version    = LIBAVUTIL_VERSION_INT,
     214             : };
     215             : 
     216             : AVCodec ff_smvjpeg_decoder = {
     217             :     .name           = "smvjpeg",
     218             :     .long_name      = NULL_IF_CONFIG_SMALL("SMV JPEG"),
     219             :     .type           = AVMEDIA_TYPE_VIDEO,
     220             :     .id             = AV_CODEC_ID_SMVJPEG,
     221             :     .priv_data_size = sizeof(SMVJpegDecodeContext),
     222             :     .init           = smvjpeg_decode_init,
     223             :     .close          = smvjpeg_decode_end,
     224             :     .decode         = smvjpeg_decode_frame,
     225             :     .priv_class     = &smvjpegdec_class,
     226             : };

Generated by: LCOV version 1.13