FFmpeg
smvjpegdec.c
Go to the documentation of this file.
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 {
36  AVFrame *picture[2]; /* pictures array */
41 
42 static inline void smv_img_pnt_plane(uint8_t **dst, uint8_t *src,
43  int src_linesize, int height, int nlines)
44 {
45  if (!dst || !src)
46  return;
47  src += (nlines) * src_linesize * height;
48  *dst = src;
49 }
50 
51 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 {
57  int i, planes_nb = 0;
58 
59  if (desc->flags & AV_PIX_FMT_FLAG_HWACCEL)
60  return;
61 
62  for (i = 0; i < desc->nb_components; i++)
63  planes_nb = FFMAX(planes_nb, desc->comp[i].plane + 1);
64 
65  for (i = 0; i < planes_nb; i++) {
66  int h = height;
67  if (i == 1 || i == 2) {
68  h = AV_CEIL_RSHIFT(height, desc->log2_chroma_h);
69  }
70  smv_img_pnt_plane(&dst_data[i], src_data[i],
71  src_linesizes[i], h, nlines);
72  }
73  if (desc->flags & AV_PIX_FMT_FLAG_PAL ||
74  desc->flags & FF_PSEUDOPAL)
75  dst_data[1] = src_data[1];
76 }
77 
79 {
81  MJpegDecodeContext *jpg = &s->jpg;
82  int ret;
83 
84  jpg->picture_ptr = NULL;
85  av_frame_free(&s->picture[0]);
86  av_frame_free(&s->picture[1]);
87  ret = avcodec_close(s->avctx);
88  av_freep(&s->avctx);
89  return ret;
90 }
91 
93 {
95  AVCodec *codec;
96  AVDictionary *thread_opt = NULL;
97  int ret = 0, r;
98 
99  s->frames_per_jpeg = 0;
100 
101  s->picture[0] = av_frame_alloc();
102  if (!s->picture[0])
103  return AVERROR(ENOMEM);
104 
105  s->picture[1] = av_frame_alloc();
106  if (!s->picture[1]) {
107  av_frame_free(&s->picture[0]);
108  return AVERROR(ENOMEM);
109  }
110 
111  s->jpg.picture_ptr = s->picture[0];
112 
113  if (avctx->extradata_size >= 4)
114  s->frames_per_jpeg = AV_RL32(avctx->extradata);
115 
116  if (s->frames_per_jpeg <= 0) {
117  av_log(avctx, AV_LOG_ERROR, "Invalid number of frames per jpeg.\n");
119  }
120 
122  if (!codec) {
123  av_log(avctx, AV_LOG_ERROR, "MJPEG codec not found\n");
124  smvjpeg_decode_end(avctx);
126  }
127 
128  s->avctx = avcodec_alloc_context3(codec);
129 
130  av_dict_set(&thread_opt, "threads", "1", 0);
131  s->avctx->refcounted_frames = 1;
132  s->avctx->flags = avctx->flags;
133  s->avctx->idct_algo = avctx->idct_algo;
134  if ((r = ff_codec_open2_recursive(s->avctx, codec, &thread_opt)) < 0) {
135  av_log(avctx, AV_LOG_ERROR, "MJPEG codec failed to open\n");
136  ret = r;
137  }
138  av_dict_free(&thread_opt);
139 
140  if (ret < 0)
141  smvjpeg_decode_end(avctx);
142  return ret;
143 }
144 
145 static int smvjpeg_decode_frame(AVCodecContext *avctx, void *data, int *data_size,
146  AVPacket *avpkt)
147 {
148  const AVPixFmtDescriptor *desc;
149  SMVJpegDecodeContext *s = avctx->priv_data;
150  AVFrame* mjpeg_data = s->picture[0];
151  int i, cur_frame = 0, ret = 0;
152 
153  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  if (cur_frame < 0)
157  cur_frame += s->frames_per_jpeg;
158 
159  /* Are we at the start of a block? */
160  if (!cur_frame) {
161  av_frame_unref(mjpeg_data);
162  ret = avcodec_decode_video2(s->avctx, mjpeg_data, &s->mjpeg_data_size, avpkt);
163  if (ret < 0) {
164  s->mjpeg_data_size = 0;
165  return ret;
166  }
167  } else if (!s->mjpeg_data_size)
168  return AVERROR(EINVAL);
169 
170  desc = av_pix_fmt_desc_get(s->avctx->pix_fmt);
171  av_assert0(desc);
172 
173  if (mjpeg_data->height % (s->frames_per_jpeg << desc->log2_chroma_h)) {
174  av_log(avctx, AV_LOG_ERROR, "Invalid height\n");
175  return AVERROR_INVALIDDATA;
176  }
177 
178  /*use the last lot... */
179  *data_size = s->mjpeg_data_size;
180 
181  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  ret = ff_set_dimensions(avctx, mjpeg_data->width, mjpeg_data->height / s->frames_per_jpeg);
186  if (ret < 0) {
187  av_log(s, AV_LOG_ERROR, "Failed to set dimensions\n");
188  return ret;
189  }
190 
191  if (*data_size) {
192  s->picture[1]->extended_data = NULL;
193  s->picture[1]->width = avctx->width;
194  s->picture[1]->height = avctx->height;
195  s->picture[1]->format = avctx->pix_fmt;
196  smv_img_pnt(s->picture[1]->data, mjpeg_data->data, mjpeg_data->linesize,
197  avctx->pix_fmt, avctx->width, avctx->height, cur_frame);
198  for (i = 0; i < AV_NUM_DATA_POINTERS; i++)
199  s->picture[1]->linesize[i] = mjpeg_data->linesize[i];
200 
201  ret = av_frame_ref(data, s->picture[1]);
202  if (ret < 0)
203  return ret;
204  }
205 
206  return avpkt->size;
207 }
208 
209 static const AVClass smvjpegdec_class = {
210  .class_name = "SMVJPEG decoder",
211  .item_name = av_default_item_name,
212  .version = LIBAVUTIL_VERSION_INT,
213 };
214 
216  .name = "smvjpeg",
217  .long_name = NULL_IF_CONFIG_SMALL("SMV JPEG"),
218  .type = AVMEDIA_TYPE_VIDEO,
219  .id = AV_CODEC_ID_SMVJPEG,
220  .priv_data_size = sizeof(SMVJpegDecodeContext),
222  .close = smvjpeg_decode_end,
224  .priv_class = &smvjpegdec_class,
225 };
avcodec_close
int avcodec_close(AVCodecContext *avctx)
Close a given AVCodecContext and free all the data associated with it (but not the AVCodecContext its...
Definition: utils.c:1143
AVCodec
AVCodec.
Definition: codec.h:190
AVPixelFormat
AVPixelFormat
Pixel format.
Definition: pixfmt.h:64
init
static av_cold int init(AVCodecContext *avctx)
Definition: avrndec.c:35
r
const char * r
Definition: vf_curves.c:114
AVERROR
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
opt.h
av_pix_fmt_desc_get
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:2549
smvjpeg_decode_frame
static int smvjpeg_decode_frame(AVCodecContext *avctx, void *data, int *data_size, AVPacket *avpkt)
Definition: smvjpegdec.c:145
av_frame_free
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:203
mjpegdec.h
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:300
AVFrame::width
int width
Definition: frame.h:358
internal.h
data
const char data[16]
Definition: mxf.c:91
AVDictionary
Definition: dict.c:30
AVFrame::data
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:314
AV_PIX_FMT_FLAG_HWACCEL
#define AV_PIX_FMT_FLAG_HWACCEL
Pixel format is an HW accelerated format.
Definition: pixdesc.h:140
AVCodecContext::flags
int flags
AV_CODEC_FLAG_*.
Definition: avcodec.h:606
ff_smvjpeg_decoder
AVCodec ff_smvjpeg_decoder
Definition: smvjpegdec.c:215
av_frame_alloc
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
Definition: frame.c:190
MJpegDecodeContext::picture_ptr
AVFrame * picture_ptr
Definition: mjpegdec.h:101
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
av_cold
#define av_cold
Definition: attributes.h:90
SMVJpegDecodeContext::mjpeg_data_size
int mjpeg_data_size
Definition: smvjpegdec.c:39
decode
static void decode(AVCodecContext *dec_ctx, AVPacket *pkt, AVFrame *frame, FILE *outfile)
Definition: decode_audio.c:71
AVCodecContext::extradata_size
int extradata_size
Definition: avcodec.h:628
avcodec_alloc_context3
AVCodecContext * avcodec_alloc_context3(const AVCodec *codec)
Allocate an AVCodecContext and set its fields to default values.
Definition: options.c:157
width
#define width
s
#define s(width, name)
Definition: cbs_vp9.c:257
AV_CEIL_RSHIFT
#define AV_CEIL_RSHIFT(a, b)
Definition: common.h:58
av_assert0
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:37
pix_fmt
static enum AVPixelFormat pix_fmt
Definition: demuxing_decoding.c:40
LIBAVUTIL_VERSION_INT
#define LIBAVUTIL_VERSION_INT
Definition: version.h:85
AVClass
Describe the class of an AVClass context structure.
Definition: log.h:67
NULL
#define NULL
Definition: coverity.c:32
av_default_item_name
const char * av_default_item_name(void *ptr)
Return the context name.
Definition: log.c:235
src
#define src
Definition: vp8dsp.c:254
MJpegDecodeContext
Definition: mjpegdec.h:46
desc
const char * desc
Definition: nvenc.c:79
ff_codec_open2_recursive
int ff_codec_open2_recursive(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options)
Call avcodec_open2 recursively by decrementing counter, unlocking mutex, calling the function and the...
Definition: utils.c:553
AVPacket::size
int size
Definition: packet.h:356
NULL_IF_CONFIG_SMALL
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition: internal.h:188
smvjpeg_decode_init
static av_cold int smvjpeg_decode_init(AVCodecContext *avctx)
Definition: smvjpegdec.c:92
av_frame_ref
int av_frame_ref(AVFrame *dst, const AVFrame *src)
Set up a new reference to the data described by the source frame.
Definition: frame.c:444
SMVJpegDecodeContext::picture
AVFrame * picture[2]
Definition: smvjpegdec.c:36
FFMAX
#define FFMAX(a, b)
Definition: common.h:94
AV_CODEC_ID_SMVJPEG
@ AV_CODEC_ID_SMVJPEG
Definition: codec_id.h:258
AV_NUM_DATA_POINTERS
#define AV_NUM_DATA_POINTERS
Definition: frame.h:301
smv_img_pnt
static void smv_img_pnt(uint8_t *dst_data[4], uint8_t *src_data[4], const int src_linesizes[4], enum AVPixelFormat pix_fmt, int width, int height, int nlines)
Definition: smvjpegdec.c:51
height
#define height
av_dict_free
void av_dict_free(AVDictionary **pm)
Free all the memory allocated for an AVDictionary struct and all keys and values.
Definition: dict.c:203
AV_CODEC_ID_MJPEG
@ AV_CODEC_ID_MJPEG
Definition: codec_id.h:56
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:269
AVPacket::pts
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
Definition: packet.h:348
AVCodecContext::extradata
uint8_t * extradata
some codecs need / can use extradata like Huffman tables.
Definition: avcodec.h:627
avcodec_decode_video2
attribute_deprecated int avcodec_decode_video2(AVCodecContext *avctx, AVFrame *picture, int *got_picture_ptr, const AVPacket *avpkt)
Decode the video frame of size avpkt->size from avpkt->data into picture.
Definition: decode.c:806
smvjpegdec_class
static const AVClass smvjpegdec_class
Definition: smvjpegdec.c:209
uint8_t
uint8_t
Definition: audio_convert.c:194
av_frame_unref
void av_frame_unref(AVFrame *frame)
Unreference all the buffers referenced by frame and reset the frame fields.
Definition: frame.c:554
AVCodecContext::idct_algo
int idct_algo
IDCT algorithm, see FF_IDCT_* below.
Definition: avcodec.h:1729
AVCodec::name
const char * name
Name of the codec implementation.
Definition: codec.h:197
AVCodecContext::height
int height
Definition: avcodec.h:699
AVCodecContext::pix_fmt
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
Definition: avcodec.h:736
avcodec.h
ret
ret
Definition: filter_design.txt:187
AVClass::class_name
const char * class_name
The name of the class; usually it is the same name as the context structure type to which the AVClass...
Definition: log.h:72
avcodec_find_decoder
AVCodec * avcodec_find_decoder(enum AVCodecID id)
Find a registered decoder with a matching codec ID.
Definition: allcodecs.c:919
AV_RL32
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_RL32
Definition: bytestream.h:88
SMVJpegDecodeContext::frames_per_jpeg
int frames_per_jpeg
Definition: smvjpegdec.c:38
AVCodecContext
main external API structure.
Definition: avcodec.h:526
AVFrame::height
int height
Definition: frame.h:358
smv_img_pnt_plane
static void smv_img_pnt_plane(uint8_t **dst, uint8_t *src, int src_linesize, int height, int nlines)
Definition: smvjpegdec.c:42
SMVJpegDecodeContext
Definition: smvjpegdec.c:34
AVERROR_DECODER_NOT_FOUND
#define AVERROR_DECODER_NOT_FOUND
Decoder not found.
Definition: error.h:52
AVMEDIA_TYPE_VIDEO
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:201
ff_set_dimensions
int ff_set_dimensions(AVCodecContext *s, int width, int height)
Check that the provided frame dimensions are valid and set them on the codec context.
Definition: utils.c:104
AVPixFmtDescriptor
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
Definition: pixdesc.h:81
AVPacket
This structure stores compressed data.
Definition: packet.h:332
AVCodecContext::priv_data
void * priv_data
Definition: avcodec.h:553
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:35
av_dict_set
int av_dict_set(AVDictionary **pm, const char *key, const char *value, int flags)
Set the given entry in *pm, overwriting an existing entry.
Definition: dict.c:70
AVCodecContext::width
int width
picture width / height.
Definition: avcodec.h:699
imgutils.h
AVFrame::linesize
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
Definition: frame.h:331
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:28
FF_PSEUDOPAL
#define FF_PSEUDOPAL
Definition: internal.h:369
AVERROR_INVALIDDATA
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:59
SMVJpegDecodeContext::avctx
AVCodecContext * avctx
Definition: smvjpegdec.c:37
h
h
Definition: vp9dsp_template.c:2038
AV_PIX_FMT_FLAG_PAL
#define AV_PIX_FMT_FLAG_PAL
Pixel format has a palette in data[1], values are indexes in this palette.
Definition: pixdesc.h:132
smvjpeg_decode_end
static av_cold int smvjpeg_decode_end(AVCodecContext *avctx)
Definition: smvjpegdec.c:78
SMVJpegDecodeContext::jpg
MJpegDecodeContext jpg
Definition: smvjpegdec.c:35