1 // Copyright 2008-present Contributors to the OpenImageIO project.
2 // SPDX-License-Identifier: BSD-3-Clause
3 // https://github.com/OpenImageIO/oiio/blob/master/LICENSE.md
4
5 extern "C" { // ffmpeg is a C api
6 #include <cerrno>
7 #include <libavcodec/avcodec.h>
8 #include <libavformat/avformat.h>
9 #include <libswscale/swscale.h>
10 #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 24, 0)
11 # include <libavutil/imgutils.h>
12 #endif
13 }
14
15 // It's hard to figure out FFMPEG versions from what they give us, so
16 // record some of the milestones once and for all for easy reference.
17 #define USE_FFMPEG_2_6 (LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(56, 26, 100))
18 #define USE_FFMPEG_2_7 (LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(56, 41, 100))
19 #define USE_FFMPEG_2_8 (LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(56, 60, 100))
20 #define USE_FFMPEG_3_0 (LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 24, 100))
21 #define USE_FFMPEG_3_1 (LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 48, 100))
22 #define USE_FFMPEG_3_2 (LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 64, 100))
23 #define USE_FFMPEG_3_3 (LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 89, 100))
24 #define USE_FFMPEG_3_4 (LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 107, 100))
25 #define USE_FFMPEG_4_0 (LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(58, 18, 100))
26 #define USE_FFMPEG_4_1 (LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(58, 35, 100))
27 #define USE_FFMPEG_4_2 (LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(58, 54, 100))
28 #define USE_FFMPEG_4_3 (LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(58, 91, 100))
29 #define USE_FFMPEG_4_4 (LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(58, 134, 100))
30
31 #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(55, 28, 1)
32 # define av_frame_alloc avcodec_alloc_frame
33 //Ancient versions used av_freep
34 # if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(54, 59, 100)
35 # define av_frame_free av_freep
36 # else
37 # define av_frame_free avcodec_free_frame
38 # endif
39 #endif
40
41 // PIX_FMT was renamed to AV_PIX_FMT on this version
42 #if LIBAVUTIL_VERSION_INT < AV_VERSION_INT(51, 74, 100)
43 # define AVPixelFormat PixelFormat
44 # define AV_PIX_FMT_RGB24 PIX_FMT_RGB24
45 # define AV_PIX_FMT_RGB48 PIX_FMT_RGB48
46 # define AV_PIX_FMT_YUVJ420P PIX_FMT_YUVJ420P
47 # define AV_PIX_FMT_YUVJ422P PIX_FMT_YUVJ422P
48 # define AV_PIX_FMT_YUVJ440P PIX_FMT_YUVJ440P
49 # define AV_PIX_FMT_YUVJ444P PIX_FMT_YUVJ444P
50 # define AV_PIX_FMT_YUV420P PIX_FMT_YUV420P
51 # define AV_PIX_FMT_YUV422P PIX_FMT_YUV422P
52 # define AV_PIX_FMT_YUV440P PIX_FMT_YUV440P
53 # define AV_PIX_FMT_YUV444P PIX_FMT_YUV444P
54 #endif
55
56 // r_frame_rate deprecated in ffmpeg
57 // see ffmpeg commit #aba232c for details
58 #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(52, 42, 0)
59 # define r_frame_rate avg_frame_rate
60 #endif
61
62 #if USE_FFMPEG_3_0
63 # define av_free_packet av_packet_unref
64 # define avpicture_get_size(fmt, w, h) av_image_get_buffer_size(fmt, w, h, 1)
65
66 inline int
avpicture_fill(AVPicture * picture,uint8_t * ptr,enum AVPixelFormat pix_fmt,int width,int height)67 avpicture_fill(AVPicture* picture, uint8_t* ptr, enum AVPixelFormat pix_fmt,
68 int width, int height)
69 {
70 AVFrame* frame = reinterpret_cast<AVFrame*>(picture);
71 return av_image_fill_arrays(frame->data, frame->linesize, ptr, pix_fmt,
72 width, height, 1);
73 }
74 #endif
75
76 #if USE_FFMPEG_3_1
77 // AVStream::codec was changed to AVStream::codecpar
78 # define stream_codec(ix) m_format_context->streams[(ix)]->codecpar
79 // avcodec_decode_video2 was deprecated.
80 // This now works by sending `avpkt` to the decoder, which buffers the
81 // decoded image in `avctx`. Then `avcodec_receive_frame` will copy the
82 // frame to `picture`.
83 inline int
receive_frame(AVCodecContext * avctx,AVFrame * picture,AVPacket * avpkt)84 receive_frame(AVCodecContext* avctx, AVFrame* picture, AVPacket* avpkt)
85 {
86 int ret;
87
88 ret = avcodec_send_packet(avctx, avpkt);
89
90 if (ret < 0)
91 return 0;
92
93 ret = avcodec_receive_frame(avctx, picture);
94
95 if (ret < 0)
96 return 0;
97
98 return 1;
99 }
100 #else
101 # define stream_codec(ix) m_format_context->streams[(ix)]->codec
102 inline int
receive_frame(AVCodecContext * avctx,AVFrame * picture,AVPacket * avpkt)103 receive_frame(AVCodecContext* avctx, AVFrame* picture, AVPacket* avpkt)
104 {
105 int ret;
106 avcodec_decode_video2(avctx, picture, &ret, avpkt);
107 return ret;
108 }
109 #endif
110
111
112
113 #if (LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(56, 56, 100))
114 # define CODEC_CAP_DELAY AV_CODEC_CAP_DELAY
115 #endif
116
117
118 #include <OpenImageIO/imageio.h>
119 #include <iostream>
120 #include <mutex>
121
122 OIIO_PLUGIN_NAMESPACE_BEGIN
123
124
125 class FFmpegInput final : public ImageInput {
126 public:
127 FFmpegInput();
128 virtual ~FFmpegInput();
format_name(void) const129 virtual const char* format_name(void) const override
130 {
131 return "FFmpeg movie";
132 }
133 virtual bool valid_file(const std::string& name) const override;
134 virtual bool open(const std::string& name, ImageSpec& spec) override;
135 virtual bool close(void) override;
current_subimage(void) const136 virtual int current_subimage(void) const override
137 {
138 lock_guard lock(m_mutex);
139 return m_subimage;
140 }
141 virtual bool seek_subimage(int subimage, int miplevel) override;
142 virtual bool read_native_scanline(int subimage, int miplevel, int y, int z,
143 void* data) override;
144 void read_frame(int pos);
145 #if 0
146 const char *metadata (const char * key);
147 bool has_metadata (const char * key);
148 #endif
149 bool seek(int pos);
150 double fps() const;
151 int64_t time_stamp(int pos) const;
152
153 private:
154 std::string m_filename;
155 int m_subimage;
156 int64_t m_nsubimages;
157 AVFormatContext* m_format_context;
158 AVCodecContext* m_codec_context;
159 AVCodec* m_codec;
160 AVFrame* m_frame;
161 AVFrame* m_rgb_frame;
162 size_t m_stride; // scanline width in bytes, a.k.a. scanline stride
163 AVPixelFormat m_dst_pix_format;
164 SwsContext* m_sws_rgb_context;
165 AVRational m_frame_rate;
166 std::vector<uint8_t> m_rgb_buffer;
167 std::vector<int> m_video_indexes;
168 int m_video_stream;
169 int64_t m_frames;
170 int m_last_search_pos;
171 int m_last_decoded_pos;
172 bool m_offset_time;
173 bool m_codec_cap_delay;
174 bool m_read_frame;
175 int64_t m_start_time;
176
177 // init to initialize state
init(void)178 void init(void)
179 {
180 m_filename.clear();
181 m_format_context = 0;
182 m_codec_context = 0;
183 m_codec = 0;
184 m_frame = 0;
185 m_rgb_frame = 0;
186 m_sws_rgb_context = 0;
187 m_stride = 0;
188 m_rgb_buffer.clear();
189 m_video_indexes.clear();
190 m_video_stream = -1;
191 m_frames = 0;
192 m_last_search_pos = 0;
193 m_last_decoded_pos = 0;
194 m_offset_time = true;
195 m_read_frame = false;
196 m_codec_cap_delay = false;
197 m_subimage = 0;
198 m_start_time = 0;
199 }
200 };
201
202
203
204 // Obligatory material to make this a recognizeable imageio plugin
205 OIIO_PLUGIN_EXPORTS_BEGIN
206
207 OIIO_EXPORT int ffmpeg_imageio_version = OIIO_PLUGIN_VERSION;
208
209 OIIO_EXPORT const char*
ffmpeg_imageio_library_version()210 ffmpeg_imageio_library_version()
211 {
212 return "FFMpeg " OIIO_FFMPEG_VERSION " (" LIBAVFORMAT_IDENT ")";
213 }
214
215 OIIO_EXPORT ImageInput*
ffmpeg_input_imageio_create()216 ffmpeg_input_imageio_create()
217 {
218 return new FFmpegInput;
219 }
220 // FFmpeg hints:
221 // AVI (Audio Video Interleaved)
222 // QuickTime / MOV
223 // raw MPEG-4 video
224 // MPEG-1 Systems / MPEG program stream
225 OIIO_EXPORT const char* ffmpeg_input_extensions[] = {
226 "avi", "mov", "qt", "mp4", "m4a", "3gp", "3g2", "mj2", "m4v", "mpg", nullptr
227 };
228
229
230 OIIO_PLUGIN_EXPORTS_END
231
232
233
FFmpegInput()234 FFmpegInput::FFmpegInput() { init(); }
235
236
237
~FFmpegInput()238 FFmpegInput::~FFmpegInput() { close(); }
239
240
241
242 bool
valid_file(const std::string & name) const243 FFmpegInput::valid_file(const std::string& name) const
244 {
245 // Quick/naive test -- just make sure the extension is valid for one of
246 // the supported file types supported by this reader.
247 for (int i = 0; ffmpeg_input_extensions[i]; ++i)
248 if (Strutil::ends_with(name, ffmpeg_input_extensions[i]))
249 return true;
250 return false;
251 }
252
253
254
255 bool
open(const std::string & name,ImageSpec & spec)256 FFmpegInput::open(const std::string& name, ImageSpec& spec)
257 {
258 // Temporary workaround: refuse to open a file whose name does not
259 // indicate that it's a movie file. This avoids the problem that ffmpeg
260 // is willing to open tiff and other files better handled by other
261 // plugins. The better long-term solution is to replace av_register_all
262 // with our own function that registers only the formats that we want
263 // this reader to handle. At some point, we will institute that superior
264 // approach, but in the mean time, this is a quick solution that 90%
265 // does the job.
266 bool valid_extension = false;
267 for (int i = 0; ffmpeg_input_extensions[i]; ++i)
268 if (Strutil::ends_with(name, ffmpeg_input_extensions[i])) {
269 valid_extension = true;
270 break;
271 }
272 if (!valid_extension) {
273 errorf("\"%s\" could not open input", name);
274 return false;
275 }
276
277 static std::once_flag init_flag;
278 std::call_once(init_flag, av_register_all);
279 const char* file_name = name.c_str();
280 av_log_set_level(AV_LOG_FATAL);
281 if (avformat_open_input(&m_format_context, file_name, NULL, NULL) != 0) {
282 // avformat_open_input allocs format_context
283 errorf("\"%s\" could not open input", file_name);
284 return false;
285 }
286 if (avformat_find_stream_info(m_format_context, NULL) < 0) {
287 errorf("\"%s\" could not find stream info", file_name);
288 return false;
289 }
290 m_video_stream = -1;
291 for (unsigned int i = 0; i < m_format_context->nb_streams; i++) {
292 if (stream_codec(i)->codec_type == AVMEDIA_TYPE_VIDEO) {
293 if (m_video_stream < 0) {
294 m_video_stream = i;
295 }
296 m_video_indexes.push_back(i); // needed for later use
297 break;
298 }
299 }
300 if (m_video_stream == -1) {
301 errorf("\"%s\" could not find a valid videostream", file_name);
302 return false;
303 }
304
305 // codec context for videostream
306 #if USE_FFMPEG_3_1
307 AVCodecParameters* par = stream_codec(m_video_stream);
308
309 m_codec = avcodec_find_decoder(par->codec_id);
310 if (!m_codec) {
311 errorf("\"%s\" can't find decoder", file_name);
312 return false;
313 }
314
315 m_codec_context = avcodec_alloc_context3(m_codec);
316 if (!m_codec_context) {
317 errorf("\"%s\" can't allocate decoder context", file_name);
318 return false;
319 }
320
321 int ret;
322
323 ret = avcodec_parameters_to_context(m_codec_context, par);
324 if (ret < 0) {
325 errorf("\"%s\" unsupported codec", file_name);
326 return false;
327 }
328 #else
329 m_codec_context = stream_codec(m_video_stream);
330
331 m_codec = avcodec_find_decoder(m_codec_context->codec_id);
332 if (!m_codec) {
333 errorf("\"%s\" unsupported codec", file_name);
334 return false;
335 }
336 #endif
337
338 if (avcodec_open2(m_codec_context, m_codec, NULL) < 0) {
339 errorf("\"%s\" could not open codec", file_name);
340 return false;
341 }
342 if (!strcmp(m_codec_context->codec->name, "mjpeg")
343 || !strcmp(m_codec_context->codec->name, "dvvideo")) {
344 m_offset_time = false;
345 }
346 m_codec_cap_delay = (bool)(m_codec_context->codec->capabilities
347 & CODEC_CAP_DELAY);
348
349 AVStream* stream = m_format_context->streams[m_video_stream];
350 if (stream->r_frame_rate.num != 0 && stream->r_frame_rate.den != 0) {
351 m_frame_rate = stream->r_frame_rate;
352 }
353
354 m_frames = stream->nb_frames;
355 m_start_time = stream->start_time;
356 if (!m_frames) {
357 seek(0);
358 AVPacket pkt;
359 av_init_packet(&pkt);
360 av_read_frame(m_format_context, &pkt);
361 int64_t first_pts = pkt.pts;
362 int64_t max_pts = 0;
363 av_free_packet(&pkt); //because seek(int) uses m_format_context
364 seek(1 << 29);
365 av_init_packet(&pkt); //Is this needed?
366 while (stream && av_read_frame(m_format_context, &pkt) >= 0) {
367 int64_t current_pts = static_cast<int64_t>(
368 av_q2d(stream->time_base) * (pkt.pts - first_pts) * fps());
369 if (current_pts > max_pts) {
370 max_pts = current_pts + 1;
371 }
372 av_free_packet(&pkt); //Always free before format_context usage
373 }
374 m_frames = max_pts;
375 }
376 m_frame = av_frame_alloc();
377 m_rgb_frame = av_frame_alloc();
378
379 AVPixelFormat src_pix_format;
380 switch (m_codec_context->pix_fmt) { // deprecation warning for YUV formats
381 case AV_PIX_FMT_YUVJ420P: src_pix_format = AV_PIX_FMT_YUV420P; break;
382 case AV_PIX_FMT_YUVJ422P: src_pix_format = AV_PIX_FMT_YUV422P; break;
383 case AV_PIX_FMT_YUVJ444P: src_pix_format = AV_PIX_FMT_YUV444P; break;
384 case AV_PIX_FMT_YUVJ440P: src_pix_format = AV_PIX_FMT_YUV440P; break;
385 default: src_pix_format = m_codec_context->pix_fmt; break;
386 }
387
388 // Assume by default that we're delivering RGB UINT8
389 int nchannels = 3;
390 TypeDesc datatype = TypeUInt8;
391 m_dst_pix_format = AV_PIX_FMT_RGB24;
392 // Look for formats that indicate we should save some different number
393 // of channels or bit depth.
394 switch (src_pix_format) {
395 // support for 10-bit and 12-bit pix_fmts
396 case AV_PIX_FMT_RGB48BE:
397 case AV_PIX_FMT_RGB48LE:
398 case AV_PIX_FMT_BGR48BE:
399 case AV_PIX_FMT_BGR48LE:
400 case AV_PIX_FMT_YUV420P9BE:
401 case AV_PIX_FMT_YUV420P9LE:
402 case AV_PIX_FMT_YUV422P9BE:
403 case AV_PIX_FMT_YUV422P9LE:
404 case AV_PIX_FMT_YUV444P9BE:
405 case AV_PIX_FMT_YUV444P9LE:
406 case AV_PIX_FMT_YUV420P10BE:
407 case AV_PIX_FMT_YUV420P10LE:
408 case AV_PIX_FMT_YUV422P10BE:
409 case AV_PIX_FMT_YUV422P10LE:
410 case AV_PIX_FMT_YUV444P10BE:
411 case AV_PIX_FMT_YUV444P10LE:
412 case AV_PIX_FMT_YUV420P12BE:
413 case AV_PIX_FMT_YUV420P12LE:
414 case AV_PIX_FMT_YUV422P12BE:
415 case AV_PIX_FMT_YUV422P12LE:
416 case AV_PIX_FMT_YUV444P12BE:
417 case AV_PIX_FMT_YUV444P12LE:
418 case AV_PIX_FMT_YUV420P14BE:
419 case AV_PIX_FMT_YUV420P14LE:
420 case AV_PIX_FMT_YUV422P14BE:
421 case AV_PIX_FMT_YUV422P14LE:
422 case AV_PIX_FMT_YUV444P14BE:
423 case AV_PIX_FMT_YUV444P14LE:
424 case AV_PIX_FMT_GBRP9BE:
425 case AV_PIX_FMT_GBRP9LE:
426 case AV_PIX_FMT_GBRP10BE:
427 case AV_PIX_FMT_GBRP10LE:
428 case AV_PIX_FMT_GBRP16BE:
429 case AV_PIX_FMT_GBRP16LE:
430 case AV_PIX_FMT_GBRP12BE:
431 case AV_PIX_FMT_GBRP12LE:
432 case AV_PIX_FMT_GBRP14BE:
433 case AV_PIX_FMT_GBRP14LE:
434 case AV_PIX_FMT_BAYER_BGGR16LE:
435 case AV_PIX_FMT_BAYER_BGGR16BE:
436 case AV_PIX_FMT_BAYER_RGGB16LE:
437 case AV_PIX_FMT_BAYER_RGGB16BE:
438 case AV_PIX_FMT_BAYER_GBRG16LE:
439 case AV_PIX_FMT_BAYER_GBRG16BE:
440 case AV_PIX_FMT_BAYER_GRBG16LE:
441 case AV_PIX_FMT_BAYER_GRBG16BE:
442 case AV_PIX_FMT_GBRAP10BE:
443 case AV_PIX_FMT_GBRAP10LE:
444 case AV_PIX_FMT_GBRAP12BE:
445 case AV_PIX_FMT_GBRAP12LE:
446 case AV_PIX_FMT_P016LE:
447 case AV_PIX_FMT_P016BE:
448 datatype = TypeUInt16;
449 m_dst_pix_format = AV_PIX_FMT_RGB48;
450 break;
451 // Grayscale 8 bit
452 case AV_PIX_FMT_GRAY8:
453 case AV_PIX_FMT_MONOWHITE:
454 case AV_PIX_FMT_MONOBLACK:
455 datatype = TypeUInt8;
456 m_dst_pix_format = AV_PIX_FMT_GRAY8;
457 break;
458 // Grayscale 16 bit
459 case AV_PIX_FMT_GRAY9BE:
460 case AV_PIX_FMT_GRAY9LE:
461 case AV_PIX_FMT_GRAY10BE:
462 case AV_PIX_FMT_GRAY10LE:
463 case AV_PIX_FMT_GRAY12BE:
464 case AV_PIX_FMT_GRAY12LE:
465 case AV_PIX_FMT_GRAY16BE:
466 case AV_PIX_FMT_GRAY16LE:
467 datatype = TypeUInt16;
468 m_dst_pix_format = AV_PIX_FMT_GRAY16;
469 break;
470 // RGBA 8 bit
471 case AV_PIX_FMT_YA8: // YA, but promote to RGBA because who cares
472 case AV_PIX_FMT_YUVA422P:
473 case AV_PIX_FMT_YUVA444P:
474 case AV_PIX_FMT_GBRAP:
475 nchannels = 4;
476 datatype = TypeUInt8;
477 m_dst_pix_format = AV_PIX_FMT_RGBA;
478 break;
479 // RGBA 16 bit
480 case AV_PIX_FMT_YA16: // YA, but promote to RGBA
481 case AV_PIX_FMT_YUVA420P9BE:
482 case AV_PIX_FMT_YUVA420P9LE:
483 case AV_PIX_FMT_YUVA422P9BE:
484 case AV_PIX_FMT_YUVA422P9LE:
485 case AV_PIX_FMT_YUVA444P9BE:
486 case AV_PIX_FMT_YUVA444P9LE:
487 case AV_PIX_FMT_YUVA420P10BE:
488 case AV_PIX_FMT_YUVA420P10LE:
489 case AV_PIX_FMT_YUVA422P10BE:
490 case AV_PIX_FMT_YUVA422P10LE:
491 case AV_PIX_FMT_YUVA444P10BE:
492 case AV_PIX_FMT_YUVA444P10LE:
493 #if USE_FFMPEG_4_2
494 case AV_PIX_FMT_YUVA422P12BE:
495 case AV_PIX_FMT_YUVA422P12LE:
496 case AV_PIX_FMT_YUVA444P12BE:
497 case AV_PIX_FMT_YUVA444P12LE:
498 #endif
499 case AV_PIX_FMT_YUVA420P16BE:
500 case AV_PIX_FMT_YUVA420P16LE:
501 case AV_PIX_FMT_YUVA422P16BE:
502 case AV_PIX_FMT_YUVA422P16LE:
503 case AV_PIX_FMT_YUVA444P16BE:
504 case AV_PIX_FMT_YUVA444P16LE:
505 case AV_PIX_FMT_GBRAP16:
506 nchannels = 4;
507 datatype = TypeUInt16;
508 m_dst_pix_format = AV_PIX_FMT_RGBA64;
509 break;
510 // RGB float
511 case AV_PIX_FMT_GBRPF32BE:
512 case AV_PIX_FMT_GBRPF32LE:
513 nchannels = 3;
514 datatype = TypeFloat;
515 m_dst_pix_format = AV_PIX_FMT_RGB48; // ? AV_PIX_FMT_GBRPF32
516 // FIXME: They don't have a type for RGB float, only GBR float.
517 // Yuck. Punt for now and save as uint16 RGB. If people care, we
518 // can return and ask for GBR float and swap order.
519 break;
520 // RGBA float
521 case AV_PIX_FMT_GBRAPF32BE:
522 case AV_PIX_FMT_GBRAPF32LE:
523 nchannels = 4;
524 datatype = TypeFloat;
525 m_dst_pix_format = AV_PIX_FMT_RGBA64; // ? AV_PIX_FMT_GBRAPF32
526 // FIXME: They don't have a type for RGBA float, only GBRA float.
527 // Yuck. Punt for now and save as uint16 RGB. If people care, we
528 // can return and ask for GBRA float and swap order.
529 break;
530
531 // Everything else is regular 8 bit RGB
532 default: break;
533 }
534
535 m_spec = ImageSpec(m_codec_context->width, m_codec_context->height,
536 nchannels, datatype);
537 m_stride = (size_t)(m_spec.scanline_bytes());
538
539 m_rgb_buffer.resize(avpicture_get_size(m_dst_pix_format,
540 m_codec_context->width,
541 m_codec_context->height),
542 0);
543
544 m_sws_rgb_context
545 = sws_getContext(m_codec_context->width, m_codec_context->height,
546 src_pix_format, m_codec_context->width,
547 m_codec_context->height, m_dst_pix_format, SWS_AREA,
548 NULL, NULL, NULL);
549
550 AVDictionaryEntry* tag = NULL;
551 while ((tag = av_dict_get(m_format_context->metadata, "", tag,
552 AV_DICT_IGNORE_SUFFIX))) {
553 m_spec.attribute(tag->key, tag->value);
554 }
555 int rat[2] = { m_frame_rate.num, m_frame_rate.den };
556 m_spec.attribute("FramesPerSecond", TypeRational, &rat);
557 m_spec.attribute("oiio:Movie", true);
558 m_spec.attribute("oiio:subimages", int(m_frames));
559 m_spec.attribute("oiio:BitsPerSample",
560 m_codec_context->bits_per_raw_sample);
561 m_spec.attribute("ffmpeg:codec_name", m_codec_context->codec->long_name);
562 m_nsubimages = m_frames;
563 spec = m_spec;
564 m_filename = name;
565 return true;
566 }
567
568
569
570 bool
seek_subimage(int subimage,int miplevel)571 FFmpegInput::seek_subimage(int subimage, int miplevel)
572 {
573 if (subimage < 0 || subimage >= m_nsubimages || miplevel > 0) {
574 return false;
575 }
576 if (subimage == m_subimage) {
577 return true;
578 }
579 m_subimage = subimage;
580 m_read_frame = false;
581 return true;
582 }
583
584
585
586 bool
read_native_scanline(int subimage,int miplevel,int y,int,void * data)587 FFmpegInput::read_native_scanline(int subimage, int miplevel, int y, int /*z*/,
588 void* data)
589 {
590 lock_guard lock(m_mutex);
591 if (!seek_subimage(subimage, miplevel))
592 return false;
593 if (!m_read_frame) {
594 read_frame(m_subimage);
595 }
596 memcpy(data, m_rgb_frame->data[0] + y * m_rgb_frame->linesize[0], m_stride);
597 return true;
598 }
599
600
601
602 bool
close(void)603 FFmpegInput::close(void)
604 {
605 if (m_codec_context)
606 avcodec_close(m_codec_context);
607 if (m_format_context)
608 avformat_close_input(&m_format_context);
609 av_free(m_format_context); // will free m_codec and m_codec_context
610 av_frame_free(&m_frame); // free after close input
611 av_frame_free(&m_rgb_frame);
612 sws_freeContext(m_sws_rgb_context);
613 init();
614 return true;
615 }
616
617
618
619 void
read_frame(int frame)620 FFmpegInput::read_frame(int frame)
621 {
622 if (m_last_decoded_pos + 1 != frame) {
623 seek(frame);
624 }
625 AVPacket pkt;
626 int finished = 0;
627 int ret = 0;
628 while ((ret = av_read_frame(m_format_context, &pkt)) == 0
629 || m_codec_cap_delay) {
630 if (ret == AVERROR_EOF) {
631 break;
632 }
633 if (pkt.stream_index == m_video_stream) {
634 if (ret < 0 && m_codec_cap_delay) {
635 pkt.data = NULL;
636 pkt.size = 0;
637 }
638
639 finished = receive_frame(m_codec_context, m_frame, &pkt);
640
641 double pts = 0;
642 if (static_cast<int64_t>(m_frame->pkt_pts)
643 != int64_t(AV_NOPTS_VALUE)) {
644 pts = av_q2d(
645 m_format_context->streams[m_video_stream]->time_base)
646 * m_frame->pkt_pts;
647 }
648
649 int current_frame = int((pts - m_start_time) * fps() + 0.5f); //???
650 //current_frame = m_frame->display_picture_number;
651 m_last_search_pos = current_frame;
652
653 if (current_frame == frame && finished) {
654 avpicture_fill(reinterpret_cast<AVPicture*>(m_rgb_frame),
655 &m_rgb_buffer[0], m_dst_pix_format,
656 m_codec_context->width, m_codec_context->height);
657 sws_scale(m_sws_rgb_context,
658 static_cast<uint8_t const* const*>(m_frame->data),
659 m_frame->linesize, 0, m_codec_context->height,
660 m_rgb_frame->data, m_rgb_frame->linesize);
661 m_last_decoded_pos = current_frame;
662 av_free_packet(&pkt);
663 break;
664 }
665 }
666 av_free_packet(&pkt);
667 }
668 m_read_frame = true;
669 }
670
671
672
673 #if 0
674 const char *
675 FFmpegInput::metadata (const char * key)
676 {
677 AVDictionaryEntry * entry = av_dict_get (m_format_context->metadata, key, NULL, 0);
678 return entry ? av_strdup(entry->value) : NULL;
679 // FIXME -- that looks suspiciously like a memory leak
680 }
681
682
683
684 bool
685 FFmpegInput::has_metadata (const char * key)
686 {
687 return av_dict_get (m_format_context->metadata, key, NULL, 0); // is there a better to check exists?
688 }
689 #endif
690
691
692
693 bool
seek(int frame)694 FFmpegInput::seek(int frame)
695 {
696 int64_t offset = time_stamp(frame);
697 int flags = AVSEEK_FLAG_BACKWARD;
698 avcodec_flush_buffers(m_codec_context);
699 av_seek_frame(m_format_context, -1, offset, flags);
700 return true;
701 }
702
703
704
705 int64_t
time_stamp(int frame) const706 FFmpegInput::time_stamp(int frame) const
707 {
708 int64_t timestamp = static_cast<int64_t>(
709 (static_cast<double>(frame)
710 / (fps()
711 * av_q2d(m_format_context->streams[m_video_stream]->time_base))));
712 if (static_cast<int64_t>(m_format_context->start_time)
713 != int64_t(AV_NOPTS_VALUE)) {
714 timestamp += static_cast<int64_t>(
715 static_cast<double>(m_format_context->start_time) * AV_TIME_BASE
716 / av_q2d(m_format_context->streams[m_video_stream]->time_base));
717 }
718 return timestamp;
719 }
720
721
722
723 double
fps() const724 FFmpegInput::fps() const
725 {
726 if (m_frame_rate.den) {
727 return av_q2d(m_frame_rate);
728 }
729 return 1.0f;
730 }
731
732 OIIO_PLUGIN_NAMESPACE_END
733