35 #include "compose.hpp"
37 #include "mono_mpeg2_picture_frame.h"
38 #include "mpeg2_transcode.h"
39 #include "scope_guard.h"
41 #include <libavcodec/avcodec.h>
45 using std::make_shared;
46 using std::shared_ptr;
48 using boost::optional;
52 MPEG2Codec::~MPEG2Codec()
54 avcodec_free_context(&_context);
59 MPEG2Decompressor::MPEG2Decompressor()
61 _codec = avcodec_find_decoder_by_name(
"mpeg2video");
66 _context = avcodec_alloc_context3(_codec);
71 int const r = avcodec_open2(_context, _codec,
nullptr);
73 avcodec_free_context(&_context);
77 _decompressed_frame = av_frame_alloc();
78 if (!_decompressed_frame) {
79 throw std::bad_alloc();
84 MPEG2Decompressor::~MPEG2Decompressor()
86 av_frame_free(&_decompressed_frame);
91 MPEG2Decompressor::decompress_frame(shared_ptr<const MonoMPEG2PictureFrame> frame)
94 auto copy = av_malloc(frame->size() + AV_INPUT_BUFFER_PADDING_SIZE);
96 throw std::bad_alloc();
98 memcpy(copy, frame->data(), frame->size());
101 av_init_packet(&packet);
102 av_packet_from_data(&packet,
reinterpret_cast<uint8_t*
>(copy), frame->size());
104 auto images = decompress_packet(&packet);
106 av_packet_unref(&packet);
113 MPEG2Decompressor::flush()
115 return decompress_packet(
nullptr);
120 MPEG2Decompressor::decompress_packet(AVPacket* packet)
122 int const r = avcodec_send_packet(_context, packet);
127 vector<FFmpegImage> images;
129 int const r = avcodec_receive_frame(_context, _decompressed_frame);
130 if (r == AVERROR(EAGAIN) || r == AVERROR_EOF) {
136 auto clone = av_frame_clone(_decompressed_frame);
138 throw std::bad_alloc();
148 MPEG2Compressor::MPEG2Compressor(
dcp::Size size,
int video_frame_rate, int64_t bit_rate)
150 _codec = avcodec_find_encoder_by_name(
"mpeg2video");
155 _context = avcodec_alloc_context3(_codec);
160 _context->width = size.width;
161 _context->height = size.height;
162 _context->time_base = AVRational{1, video_frame_rate};
163 _context->pix_fmt = AV_PIX_FMT_YUV420P;
164 _context->bit_rate = bit_rate;
166 int const r = avcodec_open2(_context, _codec,
nullptr);
168 avcodec_free_context(&_context);
174 optional<MPEG2Compressor::IndexedFrame>
175 MPEG2Compressor::send_and_receive(AVFrame
const* frame)
177 int r = avcodec_send_frame(_context, frame);
182 auto packet = av_packet_alloc();
187 r = avcodec_receive_packet(_context, packet);
188 if (r < 0 && r != AVERROR(EAGAIN)) {
193 av_packet_free(&packet);
196 if (packet->size == 0) {
200 DCP_ASSERT(_context->time_base.num == 1);
201 return IndexedFrame{make_shared<MonoMPEG2PictureFrame>(packet->data, packet->size), std::round(
static_cast<double>(packet->pts) / _context->time_base.den)};
205 optional<MPEG2Compressor::IndexedFrame>
206 MPEG2Compressor::compress_frame(
FFmpegImage const& image)
208 return send_and_receive(image.frame());
212 optional<MPEG2Compressor::IndexedFrame>
213 MPEG2Compressor::flush()
215 return send_and_receive(
nullptr);
std::pair< std::shared_ptr< MonoMPEG2PictureFrame >, int64_t > IndexedFrame
Exceptions thrown by libdcp.
Namespace for everything in libdcp.
The integer, two-dimensional size of something.