3 * Copyright (c) 2013 Ash Hughes
5 * This file is part of FFmpeg.
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.
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.
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
29 #include "libavutil/opt.h"
30 #include "libavutil/imgutils.h"
34 typedef struct SMVJpegDecodeContext
{
35 MJpegDecodeContext jpg
;
36 AVFrame
*picture
[2]; /* pictures array */
37 AVCodecContext
* avctx
;
40 } SMVJpegDecodeContext
;
42 static inline void smv_img_pnt_plane(uint8_t **dst
, uint8_t *src
,
43 int src_linesize
, int height
, int nlines
)
47 src
+= (nlines
) * src_linesize
* height
;
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 PixelFormat pix_fmt
, int width
, int height
,
56 const AVPixFmtDescriptor
*desc
= av_pix_fmt_desc_get(pix_fmt
);
59 if (desc
->flags
& AV_PIX_FMT_FLAG_HWACCEL
)
62 for (i
= 0; i
< desc
->nb_components
; i
++)
63 planes_nb
= FFMAX(planes_nb
, desc
->comp
[i
].plane
+ 1);
65 for (i
= 0; i
< planes_nb
; i
++) {
67 if (i
== 1 || i
== 2) {
68 h
= FF_CEIL_RSHIFT(height
, desc
->log2_chroma_h
);
70 smv_img_pnt_plane(&dst_data
[i
], src_data
[i
],
71 src_linesizes
[i
], h
, nlines
);
73 if (desc
->flags
& AV_PIX_FMT_FLAG_PAL
||
74 desc
->flags
& AV_PIX_FMT_FLAG_PSEUDOPAL
)
75 dst_data
[1] = src_data
[1];
78 static av_cold
int smvjpeg_decode_end(AVCodecContext
*avctx
)
80 SMVJpegDecodeContext
*s
= avctx
->priv_data
;
81 MJpegDecodeContext
*jpg
= &s
->jpg
;
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
);
92 static av_cold
int smvjpeg_decode_init(AVCodecContext
*avctx
)
94 SMVJpegDecodeContext
*s
= avctx
->priv_data
;
96 AVDictionary
*thread_opt
= NULL
;
99 s
->frames_per_jpeg
= 0;
101 s
->picture
[0] = av_frame_alloc();
103 return AVERROR(ENOMEM
);
105 s
->picture
[1] = av_frame_alloc();
106 if (!s
->picture
[1]) {
107 av_frame_free(&s
->picture
[0]);
108 return AVERROR(ENOMEM
);
111 s
->jpg
.picture_ptr
= s
->picture
[0];
113 if (avctx
->extradata_size
>= 4)
114 s
->frames_per_jpeg
= AV_RL32(avctx
->extradata
);
116 if (s
->frames_per_jpeg
<= 0) {
117 av_log(avctx
, AV_LOG_ERROR
, "Invalid number of frames per jpeg.\n");
121 codec
= avcodec_find_decoder(AV_CODEC_ID_MJPEG
);
123 av_log(avctx
, AV_LOG_ERROR
, "MJPEG codec not found\n");
127 s
->avctx
= avcodec_alloc_context3(codec
);
129 av_dict_set(&thread_opt
, "threads", "1", 0);
130 s
->avctx
->refcounted_frames
= 1;
131 s
->avctx
->flags
= avctx
->flags
;
132 s
->avctx
->idct_algo
= avctx
->idct_algo
;
133 if (ff_codec_open2_recursive(s
->avctx
, codec
, &thread_opt
) < 0) {
134 av_log(avctx
, AV_LOG_ERROR
, "MJPEG codec failed to open\n");
137 av_dict_free(&thread_opt
);
140 smvjpeg_decode_end(avctx
);
144 static int smvjpeg_decode_frame(AVCodecContext
*avctx
, void *data
, int *data_size
,
147 const AVPixFmtDescriptor
*desc
;
148 SMVJpegDecodeContext
*s
= avctx
->priv_data
;
149 AVFrame
* mjpeg_data
= s
->picture
[0];
150 int i
, cur_frame
= 0, ret
= 0;
152 cur_frame
= avpkt
->pts
% s
->frames_per_jpeg
;
154 /* Are we at the start of a block? */
156 av_frame_unref(mjpeg_data
);
157 ret
= avcodec_decode_video2(s
->avctx
, mjpeg_data
, &s
->mjpeg_data_size
, avpkt
);
158 } else if (!s
->mjpeg_data_size
)
159 return AVERROR(EINVAL
);
161 desc
= av_pix_fmt_desc_get(s
->avctx
->pix_fmt
);
162 if (desc
&& mjpeg_data
->height
% (s
->frames_per_jpeg
<< desc
->log2_chroma_h
)) {
163 av_log(avctx
, AV_LOG_ERROR
, "Invalid height\n");
164 return AVERROR_INVALIDDATA
;
167 /*use the last lot... */
168 *data_size
= s
->mjpeg_data_size
;
170 avctx
->pix_fmt
= s
->avctx
->pix_fmt
;
172 /* We shouldn't get here if frames_per_jpeg <= 0 because this was rejected
174 ret
= ff_set_dimensions(avctx
, mjpeg_data
->width
, mjpeg_data
->height
/ s
->frames_per_jpeg
);
176 av_log(s
, AV_LOG_ERROR
, "Failed to set dimensions\n");
181 s
->picture
[1]->extended_data
= NULL
;
182 s
->picture
[1]->width
= avctx
->width
;
183 s
->picture
[1]->height
= avctx
->height
;
184 s
->picture
[1]->format
= avctx
->pix_fmt
;
185 /* ff_init_buffer_info(avctx, &s->picture[1]); */
186 smv_img_pnt(s
->picture
[1]->data
, mjpeg_data
->data
, mjpeg_data
->linesize
,
187 avctx
->pix_fmt
, avctx
->width
, avctx
->height
, cur_frame
);
188 for (i
= 0; i
< AV_NUM_DATA_POINTERS
; i
++)
189 s
->picture
[1]->linesize
[i
] = mjpeg_data
->linesize
[i
];
191 ret
= av_frame_ref(data
, s
->picture
[1]);
197 static const AVClass smvjpegdec_class
= {
198 .class_name
= "SMVJPEG decoder",
199 .item_name
= av_default_item_name
,
200 .version
= LIBAVUTIL_VERSION_INT
,
203 AVCodec ff_smvjpeg_decoder
= {
205 .long_name
= NULL_IF_CONFIG_SMALL("SMV JPEG"),
206 .type
= AVMEDIA_TYPE_VIDEO
,
207 .id
= AV_CODEC_ID_SMVJPEG
,
208 .priv_data_size
= sizeof(SMVJpegDecodeContext
),
209 .init
= smvjpeg_decode_init
,
210 .close
= smvjpeg_decode_end
,
211 .decode
= smvjpeg_decode_frame
,
212 .priv_class
= &smvjpegdec_class
,