for p in ['rgb_to_xyz', 'j2k_transcode']:
obj = bld(features='cxx cxxprogram')
obj.name = p
- obj.uselib = 'BOOST_FILESYSTEM ASDCPLIB_DCPOMATIC CXML'
+ obj.uselib = 'BOOST_FILESYSTEM ASDCPLIB_DCPOMATIC CXML AVCODEC AVUTIL'
obj.cppflags = ['-g', '-O2']
obj.use = 'libdcp%s' % bld.env.API_VERSION
obj.source = "%s.cc" % p
import shutil
def dependencies(target, options):
- return (
+ deps = [
('libcxml', 'v0.17.9', options),
('openjpeg', 'ad8edaacd54a862940d0a77c41ecda5858b54d6e'),
('asdcplib', '4b5d6e8d27dfd5fb282590538068662f4dbbf1c9')
- )
+ ]
+
+ if target.platform == 'linux':
+ ffmpeg_options = { 'shared': False }
+ else:
+ ffmpeg_options = {}
+
+ if target.platform != 'linux' or target.distro != 'arch':
+ # Use distro-provided FFmpeg on Arch, otherwise our own
+ deps.append(('ffmpeg', '0b73d2f5e70a04a67aa902902c42e3025ef3bb77', ffmpeg_options))
+
+ return deps
def build(target, options):
cmd = './waf configure --disable-examples --disable-dumpimage --disable-benchmarks --prefix=%s' % target.directory
obj = bld(features='cxx cxxprogram')
obj.name = example
obj.use = 'libdcp%s' % bld.env.API_VERSION
- obj.uselib = 'OPENJPEG CXML OPENMP ASDCPLIB_DCPOMATIC BOOST_FILESYSTEM OPENSSL XMLSEC1 MAGICK'
+ obj.uselib = 'OPENJPEG CXML OPENMP ASDCPLIB_DCPOMATIC BOOST_FILESYSTEM OPENSSL XMLSEC1 MAGICK AVCODEC AVUTIL'
obj.source = example + '.cc'
obj.target = example
obj.install_path = ''
Name: libdcp
Description: DCP reading and writing library
Version: @version@
-Requires: openssl libxml++-@xmlpp_api@ xmlsec1 libasdcp-dcpomatic xerces-c
+Requires: openssl libxml++-@xmlpp_api@ xmlsec1 libasdcp-dcpomatic xerces-c libavutil libavcodec
Libs: @libs@
Cflags: -I${includedir}
#include "atmos_asset.h"
#include "compose.hpp"
#include "mono_j2k_picture_asset.h"
+#include "mono_mpeg2_picture_asset.h"
#include "smpte_subtitle_asset.h"
#include "sound_asset.h"
#include "stereo_j2k_picture_asset.h"
}
switch (type) {
case ASDCP::ESS_UNKNOWN:
+ throw ReadError("Unknown asset type");
case ASDCP::ESS_MPEG2_VES:
- throw ReadError ("MPEG2 video essences are not supported");
+ return make_shared<MonoMPEG2PictureAsset>(path);
case ASDCP::ESS_JPEG_2000:
try {
return make_shared<MonoJ2KPictureAsset>(path);
private:
friend class AtmosAsset;
friend class MonoJ2KPictureAsset;
+ friend class MonoMPEG2PictureAsset;
friend class SoundAsset;
friend class StereoJ2KPictureAsset;
#include "interop_subtitle_asset.h"
#include "metadata.h"
#include "mono_j2k_picture_asset.h"
+#include "mono_mpeg2_picture_asset.h"
#include "j2k_picture_asset.h"
#include "pkl.h"
#include "raw_convert.h"
}
} else if (
*pkl_type == remove_parameters(J2KPictureAsset::static_pkl_type(standard)) ||
+ *pkl_type == remove_parameters(MPEG2PictureAsset::static_pkl_type(standard)) ||
*pkl_type == remove_parameters(SoundAsset::static_pkl_type(standard)) ||
*pkl_type == remove_parameters(AtmosAsset::static_pkl_type(standard)) ||
*pkl_type == remove_parameters(SMPTESubtitleAsset::static_pkl_type(standard))
};
+class MPEG2CodecError : public MiscError
+{
+public:
+ explicit MPEG2CodecError(std::string message)
+ : MiscError(message)
+ {}
+};
+
+
+class MPEG2DecompressionError : public ReadError
+{
+public:
+ explicit MPEG2DecompressionError(std::string message)
+ : ReadError(message)
+ {}
+};
+
+
class BadContentKindError : public ReadError
{
public:
--- /dev/null
+/*
+ Copyright (C) 2023 Carl Hetherington <cth@carlh.net>
+
+ This file is part of libdcp.
+
+ libdcp is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ libdcp is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with libdcp. If not, see <http://www.gnu.org/licenses/>.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of portions of this program with the
+ OpenSSL library under certain conditions as described in each
+ individual source file, and distribute linked combinations
+ including the two.
+
+ You must obey the GNU General Public License in all respects
+ for all of the code used other than OpenSSL. If you modify
+ file(s) with this exception, you may extend this exception to your
+ version of the file(s), but you are not obligated to do so. If you
+ do not wish to do so, delete this exception statement from your
+ version. If you delete this exception statement from all source
+ files in the program, then also delete it here.
+*/
+
+
+#ifndef LIBDCP_FFMPEG_IMAGE_H
+#define LIBDCP_FFMPEG_IMAGE_H
+
+
+extern "C" {
+#include <libavutil/frame.h>
+}
+#include <algorithm>
+#include <vector>
+
+
+namespace dcp {
+
+
+class FFmpegImage
+{
+public:
+ explicit FFmpegImage(AVFrame* frame)
+ : _frame(frame)
+ {}
+
+ FFmpegImage(FFmpegImage const& other) = delete;
+ FFmpegImage& operator=(FFmpegImage const& other) = delete;
+
+ FFmpegImage(FFmpegImage&& other) {
+ std::swap(_frame, other._frame);
+ }
+
+ FFmpegImage& operator=(FFmpegImage&& other) {
+ std::swap(_frame, other._frame);
+ return *this;
+ }
+
+ ~FFmpegImage()
+ {
+ av_frame_free(&_frame);
+ }
+
+ AVFrame const * frame() const {
+ return _frame;
+ }
+
+private:
+ AVFrame* _frame = nullptr;
+};
+
+
+}
+
+
+#endif
+
--- /dev/null
+/*
+ Copyright (C) 2023 Carl Hetherington <cth@carlh.net>
+
+ This file is part of libdcp.
+
+ libdcp is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ libdcp is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with libdcp. If not, see <http://www.gnu.org/licenses/>.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of portions of this program with the
+ OpenSSL library under certain conditions as described in each
+ individual source file, and distribute linked combinations
+ including the two.
+
+ You must obey the GNU General Public License in all respects
+ for all of the code used other than OpenSSL. If you modify
+ file(s) with this exception, you may extend this exception to your
+ version of the file(s), but you are not obligated to do so. If you
+ do not wish to do so, delete this exception statement from your
+ version. If you delete this exception statement from all source
+ files in the program, then also delete it here.
+*/
+
+
+#include "filesystem.h"
+#include "mono_mpeg2_picture_asset.h"
+#include "mono_mpeg2_picture_asset_reader.h"
+#include <asdcp/AS_DCP.h>
+
+
+using std::shared_ptr;
+using namespace dcp;
+
+
+MonoMPEG2PictureAsset::MonoMPEG2PictureAsset(boost::filesystem::path file)
+ : MPEG2PictureAsset(file)
+{
+ Kumu::FileReaderFactory factory;
+ ASDCP::MPEG2::MXFReader reader(factory);
+ auto const result = reader.OpenRead(dcp::filesystem::fix_long_path(file).string().c_str());
+ if (ASDCP_FAILURE(result)) {
+ boost::throw_exception(MXFFileError("could not open MXF file for reading", file.string(), result));
+ }
+
+ ASDCP::MPEG2::VideoDescriptor desc;
+ if (ASDCP_FAILURE(reader.FillVideoDescriptor(desc))) {
+ boost::throw_exception(ReadError("could not read video MXF information"));
+ }
+
+ read_video_descriptor(desc);
+
+ ASDCP::WriterInfo info;
+ if (ASDCP_FAILURE(reader.FillWriterInfo(info))) {
+ boost::throw_exception(ReadError("could not read video MXF information"));
+ }
+
+ _id = read_writer_info(info);
+}
+
+
+shared_ptr<MonoMPEG2PictureAssetReader>
+MonoMPEG2PictureAsset::start_read () const
+{
+ /* Can't use make_shared here as the MonoMPEG2PictureAssetReader constructor is private */
+ return shared_ptr<MonoMPEG2PictureAssetReader>(new MonoMPEG2PictureAssetReader(this, key(), standard()));
+
+}
--- /dev/null
+/*
+ Copyright (C) 2023 Carl Hetherington <cth@carlh.net>
+
+ This file is part of libdcp.
+
+ libdcp is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ libdcp is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with libdcp. If not, see <http://www.gnu.org/licenses/>.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of portions of this program with the
+ OpenSSL library under certain conditions as described in each
+ individual source file, and distribute linked combinations
+ including the two.
+
+ You must obey the GNU General Public License in all respects
+ for all of the code used other than OpenSSL. If you modify
+ file(s) with this exception, you may extend this exception to your
+ version of the file(s), but you are not obligated to do so. If you
+ do not wish to do so, delete this exception statement from your
+ version. If you delete this exception statement from all source
+ files in the program, then also delete it here.
+*/
+
+
+#ifndef LIBDCP_MONO_MPEG2_PICTURE_ASSET_H
+#define LIBDCP_MONO_MPEG2_PICTURE_ASSET_H
+
+
+/** @file src/mono_mpeg2_picture_asset.h
+ * @brief MonoMPEG2PictureAsset class
+ */
+
+
+#include "mpeg2_picture_asset.h"
+#include "mono_mpeg2_picture_asset_reader.h"
+
+
+namespace dcp {
+
+
+class MonoMPEG2PictureAsset : public MPEG2PictureAsset
+{
+public:
+ explicit MonoMPEG2PictureAsset(boost::filesystem::path file);
+
+ std::shared_ptr<MonoMPEG2PictureAssetReader> start_read() const;
+};
+
+
+
+}
+
+
+#endif
--- /dev/null
+/*
+ Copyright (C) 2023 Carl Hetherington <cth@carlh.net>
+
+ This file is part of libdcp.
+
+ libdcp is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ libdcp is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with libdcp. If not, see <http://www.gnu.org/licenses/>.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of portions of this program with the
+ OpenSSL library under certain conditions as described in each
+ individual source file, and distribute linked combinations
+ including the two.
+
+ You must obey the GNU General Public License in all respects
+ for all of the code used other than OpenSSL. If you modify
+ file(s) with this exception, you may extend this exception to your
+ version of the file(s), but you are not obligated to do so. If you
+ do not wish to do so, delete this exception statement from your
+ version. If you delete this exception statement from all source
+ files in the program, then also delete it here.
+*/
+
+
+/** @file src/mono_mpeg2_picture_asset_reader.h
+ * @brief MonoJ2KPictureAssetReader typedef
+ */
+
+
+#ifndef LIBDCP_MONO_MPEG2_PICTURE_ASSET_READER_H
+#define LIBDCP_MONO_MPEG2_PICTURE_ASSET_READER_H
+
+
+#include "asset_reader.h"
+#include "mono_mpeg2_picture_frame.h"
+
+
+namespace dcp {
+
+
+typedef AssetReader<ASDCP::MPEG2::MXFReader, MonoMPEG2PictureFrame> MonoMPEG2PictureAssetReader;
+
+
+}
+
+
+#endif
+
--- /dev/null
+/*
+ Copyright (C) 2023 Carl Hetherington <cth@carlh.net>
+
+ This file is part of libdcp.
+
+ libdcp is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ libdcp is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with libdcp. If not, see <http://www.gnu.org/licenses/>.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of portions of this program with the
+ OpenSSL library under certain conditions as described in each
+ individual source file, and distribute linked combinations
+ including the two.
+
+ You must obey the GNU General Public License in all respects
+ for all of the code used other than OpenSSL. If you modify
+ file(s) with this exception, you may extend this exception to your
+ version of the file(s), but you are not obligated to do so. If you
+ do not wish to do so, delete this exception statement from your
+ version. If you delete this exception statement from all source
+ files in the program, then also delete it here.
+*/
+
+
+#include "compose.hpp"
+#include "mono_mpeg2_picture_frame.h"
+
+
+using std::make_shared;
+using std::shared_ptr;
+using namespace dcp;
+
+
+
+/** Make a picture frame from a 2D (monoscopic) asset.
+ * @param reader Reader for the asset's MXF file.
+ * @param n Frame within the asset, not taking EntryPoint into account.
+ * @param c Context for decryption, or 0.
+ * @param check_hmac true to check the HMAC and give an error if it is not as expected.
+ */
+MonoMPEG2PictureFrame::MonoMPEG2PictureFrame(ASDCP::MPEG2::MXFReader* reader, int n, shared_ptr<DecryptionContext> context, bool check_hmac)
+{
+ /* XXX: unfortunate guesswork on this buffer size */
+ _buffer = make_shared<ASDCP::MPEG2::FrameBuffer>(4 * Kumu::Megabyte);
+
+ auto const r = reader->ReadFrame(n, *_buffer, context->context(), check_hmac ? context->hmac() : nullptr);
+
+ if (ASDCP_FAILURE(r)) {
+ boost::throw_exception(ReadError(String::compose("could not read video frame %1 (%2)", n, static_cast<int>(r))));
+ }
+}
+
+
+uint8_t const *
+MonoMPEG2PictureFrame::data() const
+{
+ return _buffer->RoData();
+}
+
+
+uint8_t *
+MonoMPEG2PictureFrame::data()
+{
+ return _buffer->Data();
+}
+
+
+int
+MonoMPEG2PictureFrame::size() const
+{
+ return _buffer->Size();
+}
+
--- /dev/null
+/*
+ Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
+
+ This file is part of libdcp.
+
+ libdcp is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ libdcp is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with libdcp. If not, see <http://www.gnu.org/licenses/>.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of portions of this program with the
+ OpenSSL library under certain conditions as described in each
+ individual source file, and distribute linked combinations
+ including the two.
+
+ You must obey the GNU General Public License in all respects
+ for all of the code used other than OpenSSL. If you modify
+ file(s) with this exception, you may extend this exception to your
+ version of the file(s), but you are not obligated to do so. If you
+ do not wish to do so, delete this exception statement from your
+ version. If you delete this exception statement from all source
+ files in the program, then also delete it here.
+*/
+
+
+#ifndef LIBDCP_MONO_MPEG2_PICTURE_FRAME_H
+#define LIBDCP_MONO_MPEG2_PICTURE_FRAME_H
+
+
+#include "asset_reader.h"
+#include "data.h"
+
+
+namespace dcp {
+
+
+class MonoMPEG2PictureFrame : public Data
+{
+public:
+ MonoMPEG2PictureFrame(MonoMPEG2PictureFrame const&) = delete;
+ MonoMPEG2PictureFrame& operator=(MonoMPEG2PictureFrame const&) = delete;
+
+ /** @return Pointer to MPEG2 data */
+ uint8_t const * data() const override;
+
+ /** @return Pointer to MPEG2 data */
+ uint8_t* data () override;
+
+ /** @return Size of MPEG2 data in bytes */
+ int size() const override;
+
+private:
+ /* XXX: this is a bit of a shame, but I tried friend MonoMPEG2PictureAssetReader and it's
+ rejected by some (seemingly older) GCCs.
+ */
+ friend class AssetReader<ASDCP::MPEG2::MXFReader, MonoMPEG2PictureFrame>;
+
+ MonoMPEG2PictureFrame(ASDCP::MPEG2::MXFReader* reader, int n, std::shared_ptr<DecryptionContext>, bool check_hmac);
+
+ std::shared_ptr<ASDCP::MPEG2::FrameBuffer> _buffer;
+};
+
+
+}
+
+
+#endif
--- /dev/null
+/*
+ Copyright (C) 2023 Carl Hetherington <cth@carlh.net>
+
+ This file is part of libdcp.
+
+ libdcp is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ libdcp is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with libdcp. If not, see <http://www.gnu.org/licenses/>.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of portions of this program with the
+ OpenSSL library under certain conditions as described in each
+ individual source file, and distribute linked combinations
+ including the two.
+
+ You must obey the GNU General Public License in all respects
+ for all of the code used other than OpenSSL. If you modify
+ file(s) with this exception, you may extend this exception to your
+ version of the file(s), but you are not obligated to do so. If you
+ do not wish to do so, delete this exception statement from your
+ version. If you delete this exception statement from all source
+ files in the program, then also delete it here.
+*/
+
+
+#include "mpeg2_picture_asset.h"
+
+
+using std::string;
+using namespace dcp;
+
+
+MPEG2PictureAsset::MPEG2PictureAsset(boost::filesystem::path file)
+ : PictureAsset(file)
+{
+
+}
+
+
+void
+MPEG2PictureAsset::read_video_descriptor(ASDCP::MPEG2::VideoDescriptor const& descriptor)
+{
+ _size.width = descriptor.StoredWidth;
+ _size.height = descriptor.StoredHeight;
+ _edit_rate = Fraction(descriptor.EditRate.Numerator, descriptor.EditRate.Denominator);
+ _intrinsic_duration = descriptor.ContainerDuration;
+ _frame_rate = Fraction(descriptor.SampleRate.Numerator, descriptor.SampleRate.Denominator);
+ _screen_aspect_ratio = Fraction(descriptor.AspectRatio.Numerator, descriptor.AspectRatio.Denominator);
+}
+
+
+string
+MPEG2PictureAsset::pkl_type (Standard standard) const
+{
+ DCP_ASSERT(standard == Standard::INTEROP);
+ return "application/x-smpte-mxf;asdcpKind=Picture";
+}
+
+
+string
+MPEG2PictureAsset::static_pkl_type(Standard standard)
+{
+ DCP_ASSERT(standard == Standard::INTEROP);
+ return "application/x-smpte-mxf;asdcpKind=Picture";
+}
--- /dev/null
+/*
+ Copyright (C) 2023 Carl Hetherington <cth@carlh.net>
+
+ This file is part of libdcp.
+
+ libdcp is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ libdcp is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with libdcp. If not, see <http://www.gnu.org/licenses/>.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of portions of this program with the
+ OpenSSL library under certain conditions as described in each
+ individual source file, and distribute linked combinations
+ including the two.
+
+ You must obey the GNU General Public License in all respects
+ for all of the code used other than OpenSSL. If you modify
+ file(s) with this exception, you may extend this exception to your
+ version of the file(s), but you are not obligated to do so. If you
+ do not wish to do so, delete this exception statement from your
+ version. If you delete this exception statement from all source
+ files in the program, then also delete it here.
+*/
+
+
+#ifndef LIBDCP_MPEG2_PICTURE_ASSET_H
+#define LIBDCP_MPEG2_PICTURE_ASSET_H
+
+
+/** @file src/mpeg2_picture_asset.h
+ * @brief MPEG2PictureAsset class
+ */
+
+
+#include "picture_asset.h"
+#include <boost/filesystem/path.hpp>
+
+
+namespace ASDCP {
+ namespace MPEG2 {
+ struct VideoDescriptor;
+ }
+}
+
+
+namespace dcp {
+
+
+class MPEG2PictureAsset : public PictureAsset
+{
+public:
+ explicit MPEG2PictureAsset(boost::filesystem::path file);
+
+ static std::string static_pkl_type(Standard standard);
+
+protected:
+ void read_video_descriptor(ASDCP::MPEG2::VideoDescriptor const& descriptor);
+
+private:
+ std::string pkl_type(Standard standard) const override;
+};
+
+
+}
+
+
+#endif
+
--- /dev/null
+/*
+ Copyright (C) 2023 Carl Hetherington <cth@carlh.net>
+
+ This file is part of libdcp.
+
+ libdcp is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ libdcp is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with libdcp. If not, see <http://www.gnu.org/licenses/>.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of portions of this program with the
+ OpenSSL library under certain conditions as described in each
+ individual source file, and distribute linked combinations
+ including the two.
+
+ You must obey the GNU General Public License in all respects
+ for all of the code used other than OpenSSL. If you modify
+ file(s) with this exception, you may extend this exception to your
+ version of the file(s), but you are not obligated to do so. If you
+ do not wish to do so, delete this exception statement from your
+ version. If you delete this exception statement from all source
+ files in the program, then also delete it here.
+*/
+
+
+#include "compose.hpp"
+#include "exceptions.h"
+#include "mono_mpeg2_picture_frame.h"
+#include "mpeg2_transcode.h"
+extern "C" {
+#include <libavcodec/avcodec.h>
+}
+
+
+using std::shared_ptr;
+using std::vector;
+using namespace dcp;
+
+
+MPEG2Codec::~MPEG2Codec()
+{
+ avcodec_free_context(&_context);
+}
+
+
+
+MPEG2Decompressor::MPEG2Decompressor()
+{
+ _codec = avcodec_find_decoder_by_name("mpeg2video");
+ if (!_codec) {
+ throw MPEG2CodecError("could not find codec");
+ }
+
+ _context = avcodec_alloc_context3(_codec);
+ if (!_context) {
+ throw MPEG2CodecError("could not allocate codec context");
+ }
+
+ int const r = avcodec_open2(_context, _codec, nullptr);
+ if (r < 0) {
+ avcodec_free_context(&_context);
+ throw MPEG2CodecError("could not open codec");
+ }
+
+ _decompressed_frame = av_frame_alloc();
+ if (!_decompressed_frame) {
+ throw std::bad_alloc();
+ }
+}
+
+
+MPEG2Decompressor::~MPEG2Decompressor()
+{
+ av_frame_free(&_decompressed_frame);
+}
+
+
+vector<FFmpegImage>
+MPEG2Decompressor::decompress_frame(shared_ptr<const MonoMPEG2PictureFrame> frame)
+{
+ /* XXX: can we avoid this? */
+ auto copy = av_malloc(frame->size() + AV_INPUT_BUFFER_PADDING_SIZE);
+ if (!copy) {
+ throw std::bad_alloc();
+ }
+ memcpy(copy, frame->data(), frame->size());
+
+ AVPacket packet;
+ av_init_packet(&packet);
+ av_packet_from_data(&packet, reinterpret_cast<uint8_t*>(copy), frame->size());
+
+ auto images = decompress_packet(&packet);
+
+ av_packet_unref(&packet);
+
+ return images;
+}
+
+
+vector<FFmpegImage>
+MPEG2Decompressor::flush()
+{
+ return decompress_packet(nullptr);
+}
+
+
+vector<FFmpegImage>
+MPEG2Decompressor::decompress_packet(AVPacket* packet)
+{
+ int const r = avcodec_send_packet(_context, packet);
+ if (r < 0) {
+ throw MPEG2DecompressionError(String::compose("avcodec_send_packet failed (%1)", r));
+ }
+
+ vector<FFmpegImage> images;
+ while (true) {
+ int const r = avcodec_receive_frame(_context, _decompressed_frame);
+ if (r == AVERROR(EAGAIN) || r == AVERROR_EOF) {
+ break;
+ } else if (r < 0) {
+ throw MPEG2DecompressionError("avcodec_receive_frame failed");
+ }
+
+ auto clone = av_frame_clone(_decompressed_frame);
+ if (!clone) {
+ throw std::bad_alloc();
+ }
+
+ images.push_back(FFmpegImage(clone));
+ }
+
+ return images;
+}
+
--- /dev/null
+/*
+ Copyright (C) 2023 Carl Hetherington <cth@carlh.net>
+
+ This file is part of libdcp.
+
+ libdcp is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ libdcp is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with libdcp. If not, see <http://www.gnu.org/licenses/>.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of portions of this program with the
+ OpenSSL library under certain conditions as described in each
+ individual source file, and distribute linked combinations
+ including the two.
+
+ You must obey the GNU General Public License in all respects
+ for all of the code used other than OpenSSL. If you modify
+ file(s) with this exception, you may extend this exception to your
+ version of the file(s), but you are not obligated to do so. If you
+ do not wish to do so, delete this exception statement from your
+ version. If you delete this exception statement from all source
+ files in the program, then also delete it here.
+*/
+
+
+#ifndef LIBDCP_MPEG2_TRANSCODE_H
+#define LIBDCP_MPEG2_TRANSCODE_H
+
+
+#include "ffmpeg_image.h"
+#include <memory>
+
+
+struct AVCodec;
+struct AVCodecContext;
+struct AVFrame;
+struct AVPacket;
+
+
+namespace dcp {
+
+
+class MonoMPEG2PictureFrame;
+
+
+class MPEG2Codec
+{
+public:
+ MPEG2Codec() = default;
+ virtual ~MPEG2Codec();
+
+ MPEG2Codec(MPEG2Codec const&) = delete;
+ MPEG2Codec& operator=(MPEG2Codec const&) = delete;
+
+protected:
+ AVCodec const* _codec;
+ AVCodecContext* _context;
+};
+
+
+class MPEG2Decompressor : public MPEG2Codec
+{
+public:
+ MPEG2Decompressor();
+ ~MPEG2Decompressor();
+
+ std::vector<FFmpegImage> decompress_frame(std::shared_ptr<const MonoMPEG2PictureFrame> frame);
+ std::vector<FFmpegImage> flush();
+
+private:
+ std::vector<FFmpegImage> decompress_packet(AVPacket* packet);
+
+ AVFrame* _decompressed_frame;
+};
+
+
+}
+
+
+#endif
{
for (auto const& i: kdm.keys()) {
if (_main_picture && i.id() == _main_picture->key_id() && _main_picture->asset_ref().resolved()) {
- _main_picture->asset()->set_key (i.key());
+ _main_picture->j2k_asset()->set_key(i.key());
}
if (_main_sound && i.id() == _main_sound->key_id() && _main_sound->asset_ref().resolved()) {
_main_sound->asset()->set_key (i.key());
using namespace dcp;
-ReelMonoPictureAsset::ReelMonoPictureAsset (std::shared_ptr<MonoJ2KPictureAsset> asset, int64_t entry_point)
+ReelMonoPictureAsset::ReelMonoPictureAsset(std::shared_ptr<PictureAsset> asset, int64_t entry_point)
: ReelPictureAsset (asset, entry_point)
{
#include "reel_picture_asset.h"
#include "mono_j2k_picture_asset.h"
+#include "mono_mpeg2_picture_asset.h"
namespace dcp {
class ReelMonoPictureAsset : public ReelPictureAsset
{
public:
- ReelMonoPictureAsset (std::shared_ptr<MonoJ2KPictureAsset> asset, int64_t entry_point);
+ ReelMonoPictureAsset(std::shared_ptr<PictureAsset> asset, int64_t entry_point);
explicit ReelMonoPictureAsset (std::shared_ptr<const cxml::Node>);
- /** @return the MonoJ2KPictureAsset that this object refers to */
- std::shared_ptr<const MonoJ2KPictureAsset> mono_asset () const {
+ /** @return the MonoJ2KPictureAsset that this object refers to, if applicable */
+ std::shared_ptr<const MonoJ2KPictureAsset> mono_j2k_asset() const {
return asset_of_type<const MonoJ2KPictureAsset>();
}
/** @return the MonoJ2KPictureAsset that this object refers to */
- std::shared_ptr<MonoJ2KPictureAsset> mono_asset () {
+ std::shared_ptr<MonoJ2KPictureAsset> mono_j2k_asset() {
return asset_of_type<MonoJ2KPictureAsset>();
}
+ /** @return the MonoMPEG2PictureAsset that this object refers to, if applicable */
+ std::shared_ptr<const MonoMPEG2PictureAsset> mono_mpeg2_asset() const {
+ return asset_of_type<const MonoMPEG2PictureAsset>();
+ }
+
+ /** @return the MonoMPEG2PictureAsset that this object refers to */
+ std::shared_ptr<MonoMPEG2PictureAsset> mono_mpeg2_asset() {
+ return asset_of_type<MonoMPEG2PictureAsset>();
+ }
+
private:
std::string cpl_node_name (Standard standard) const override;
};
using namespace dcp;
-ReelPictureAsset::ReelPictureAsset (shared_ptr<J2KPictureAsset> asset, int64_t entry_point)
+ReelPictureAsset::ReelPictureAsset(shared_ptr<PictureAsset> asset, int64_t entry_point)
: ReelFileAsset (asset, asset->key_id(), asset->id(), asset->edit_rate(), asset->intrinsic_duration(), entry_point)
, _frame_rate (asset->frame_rate ())
, _screen_aspect_ratio (asset->screen_aspect_ratio ())
#include "reel_file_asset.h"
#include "j2k_picture_asset.h"
+#include "mpeg2_picture_asset.h"
namespace dcp {
class ReelPictureAsset : public ReelFileAsset
{
public:
- ReelPictureAsset (std::shared_ptr<J2KPictureAsset> asset, int64_t entry_point);
+ ReelPictureAsset(std::shared_ptr<PictureAsset> asset, int64_t entry_point);
explicit ReelPictureAsset (std::shared_ptr<const cxml::Node>);
- /** @return the J2KPictureAsset that this object refers to */
- std::shared_ptr<const J2KPictureAsset> asset () const {
+ /** @return the PictureAsset that this object refers to, if applicable */
+ std::shared_ptr<const PictureAsset> asset() const {
+ return asset_of_type<const PictureAsset>();
+ }
+
+ /** @return the PictureAsset that this object refers to, if applicable */
+ std::shared_ptr<PictureAsset> asset() {
+ return asset_of_type<PictureAsset>();
+ }
+
+ /** @return the J2KPictureAsset that this object refers to, if applicable */
+ std::shared_ptr<const J2KPictureAsset> j2k_asset() const {
return asset_of_type<const J2KPictureAsset>();
}
- /** @return the J2KPictureAsset that this object refers to */
- std::shared_ptr<J2KPictureAsset> asset () {
+ /** @return the J2KPictureAsset that this object refers to, if applicable */
+ std::shared_ptr<J2KPictureAsset> j2k_asset() {
return asset_of_type<J2KPictureAsset>();
}
+ /** @return the MPEG2PictureAsset that this object refers to, if applicable */
+ std::shared_ptr<const MPEG2PictureAsset> mpeg2_asset() const {
+ return asset_of_type<const MPEG2PictureAsset>();
+ }
+
+ /** @return the MPEG2PictureAsset that this object refers to, if applicable */
+ std::shared_ptr<MPEG2PictureAsset> mpeg2_asset() {
+ return asset_of_type<MPEG2PictureAsset>();
+ }
+
virtual xmlpp::Element* write_to_cpl(xmlpp::Element* node, Standard standard) const override;
+
bool equals(std::shared_ptr<const ReelPictureAsset>, EqualityOptions const&, NoteHandler) const;
/** @return picture frame rate */
mono_j2k_picture_asset.cc
mono_j2k_picture_asset_writer.cc
mono_j2k_picture_frame.cc
+ mono_mpeg2_picture_asset.cc
+ mono_mpeg2_picture_frame.cc
+ mpeg2_picture_asset.cc
+ mpeg2_transcode.cc
mxf.cc
name_format.cc
object.cc
identity_transfer_function.h
interop_load_font_node.h
interop_subtitle_asset.h
+ ffmpeg_image.h
j2k_picture_asset.h
j2k_picture_asset_writer.h
j2k_transcode.h
mono_j2k_picture_asset_reader.h
mono_j2k_picture_asset_writer.h
mono_j2k_picture_frame.h
+ mono_mpeg2_picture_asset.h
+ mono_mpeg2_picture_asset_reader.h
+ mono_mpeg2_picture_frame.h
+ mpeg2_picture_asset.h
+ mpeg2_transcode.h
mxf.h
name_format.h
object.h
obj.name = 'libdcp%s' % bld.env.API_VERSION
obj.target = 'dcp%s' % bld.env.API_VERSION
obj.export_includes = ['.']
- obj.uselib = 'BOOST_FILESYSTEM BOOST_SIGNALS2 BOOST_DATETIME OPENSSL SIGC++ LIBXML++ OPENJPEG CXML XMLSEC1 ASDCPLIB_DCPOMATIC XERCES'
+ obj.uselib = 'BOOST_FILESYSTEM BOOST_SIGNALS2 BOOST_DATETIME OPENSSL SIGC++ LIBXML++ OPENJPEG CXML XMLSEC1 ASDCPLIB_DCPOMATIC XERCES AVCODEC AVUTIL'
obj.source = source
# Library for gcov
obj.name = 'libdcp%s_gcov' % bld.env.API_VERSION
obj.target = 'dcp%s_gcov' % bld.env.API_VERSION
obj.export_includes = ['.']
- obj.uselib = 'BOOST_FILESYSTEM BOOST_SIGNALS2 BOOST_DATETIME OPENSSL SIGC++ LIBXML++ OPENJPEG CXML XMLSEC1 ASDCPLIB_DCPOMATIC XERCES'
+ obj.uselib = 'BOOST_FILESYSTEM BOOST_SIGNALS2 BOOST_DATETIME OPENSSL SIGC++ LIBXML++ OPENJPEG CXML XMLSEC1 ASDCPLIB_DCPOMATIC XERCES AVCODEC AVUTIL'
obj.use = 'libkumu-libdcp%s libasdcp-libdcp%s' % (bld.env.API_VERSION, bld.env.API_VERSION)
obj.source = source
obj.cppflags = ['-fprofile-arcs', '-ftest-coverage', '-fno-inline', '-fno-default-inline', '-fno-elide-constructors', '-g', '-O0']
dcp::DCP B ("build/test/" + name);
auto reel = make_shared<dcp::Reel>();
- BOOST_REQUIRE (A_picture->mono_asset());
- BOOST_REQUIRE (A_picture->mono_asset()->file());
- copy_file (A_picture->mono_asset()->file().get(), path("build") / "test" / name / picture);
+ BOOST_REQUIRE(A_picture->mono_j2k_asset());
+ BOOST_REQUIRE(A_picture->mono_j2k_asset()->file());
+ copy_file(A_picture->mono_j2k_asset()->file().get(), path("build") / "test" / name / picture);
reel->add(make_shared<dcp::ReelMonoPictureAsset>(make_shared<dcp::MonoJ2KPictureAsset>(path("build") / "test" / name / picture), 0));
auto reader = A_sound->asset()->start_read();
ov->write_xml ();
auto ov_reel = ov->cpls()[0]->reels()[0];
- auto ov_reel_picture = make_shared<dcp::ReelMonoPictureAsset>(dynamic_pointer_cast<dcp::ReelMonoPictureAsset>(ov_reel->main_picture())->mono_asset(), 0);
+ auto ov_reel_picture = make_shared<dcp::ReelMonoPictureAsset>(dynamic_pointer_cast<dcp::ReelMonoPictureAsset>(ov_reel->main_picture())->mono_j2k_asset(), 0);
auto ov_reel_sound = make_shared<dcp::ReelSoundAsset>(ov_reel->main_sound()->asset(), 0);
/* Make VF */
--- /dev/null
+/*
+ Copyright (C) 2023 Carl Hetherington <cth@carlh.net>
+
+ This file is part of libdcp.
+
+ libdcp is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ libdcp is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with libdcp. If not, see <http://www.gnu.org/licenses/>.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of portions of this program with the
+ OpenSSL library under certain conditions as described in each
+ individual source file, and distribute linked combinations
+ including the two.
+
+ You must obey the GNU General Public License in all respects
+ for all of the code used other than OpenSSL. If you modify
+ file(s) with this exception, you may extend this exception to your
+ version of the file(s), but you are not obligated to do so. If you
+ do not wish to do so, delete this exception statement from your
+ version. If you delete this exception statement from all source
+ files in the program, then also delete it here.
+*/
+
+
+#include "mono_mpeg2_picture_asset.h"
+#include "mpeg2_transcode.h"
+#include "test.h"
+#include <boost/test/unit_test.hpp>
+
+extern "C" {
+#include <libavcodec/avcodec.h>
+}
+
+
+BOOST_AUTO_TEST_CASE(mpeg_mono_picture_read_test)
+{
+ dcp::MonoMPEG2PictureAsset asset(private_test / "data" / "mas" / "r2.mxf" );
+ std::cout << "frame rate " << asset.frame_rate().numerator << "\n";
+ std::cout << "duration " << asset.intrinsic_duration() << "\n";
+
+ auto reader = asset.start_read();
+
+ dcp::MPEG2Decompressor decompressor;
+ for (auto i = 0; i < asset.intrinsic_duration(); ++i) {
+ auto images = decompressor.decompress_frame(reader->get_frame(i));
+ BOOST_CHECK_EQUAL(images.size(), i == 0 ? 0U : 1U);
+ }
+
+ auto images = decompressor.flush();
+ BOOST_CHECK_EQUAL(images.size(), 1U);
+}
+
def build(bld):
obj = bld(features='cxx cxxprogram')
obj.name = 'tests'
- obj.uselib = 'BOOST_TEST BOOST_FILESYSTEM BOOST_DATETIME OPENJPEG CXML XMLSEC1 SNDFILE OPENMP ASDCPLIB_DCPOMATIC LIBXML++ OPENSSL XERCES DL'
+ obj.uselib = 'BOOST_TEST BOOST_FILESYSTEM BOOST_DATETIME OPENJPEG CXML XMLSEC1 SNDFILE OPENMP ASDCPLIB_DCPOMATIC LIBXML++ OPENSSL XERCES DL AVCODEC AVUTIL'
obj.cppflags = ['-fno-inline', '-fno-elide-constructors', '-g', '-O0']
if bld.env['CXX_NAME'] == 'gcc':
obj.cppflags.append('-fno-default-inline')
make_digest_test.cc
markers_test.cc
mca_test.cc
+ mono_mpeg2_picture_read_test.cc
kdm_test.cc
key_test.cc
language_tag_test.cc
obj = bld(features='cxx cxxprogram')
obj.name = 'subs_in_out'
- obj.uselib = 'BOOST_TEST BOOST_FILESYSTEM OPENJPEG CXML OPENMP ASDCPLIB_DCPOMATIC XMLSEC1 OPENSSL DL LIBXML++'
+ obj.uselib = 'BOOST_TEST BOOST_FILESYSTEM OPENJPEG CXML OPENMP ASDCPLIB_DCPOMATIC XMLSEC1 OPENSSL DL LIBXML++ AVCODEC AVUTIL'
obj.cppflags = ['-fno-inline', '-fno-elide-constructors', '-g', '-O0']
if bld.env['CXX_NAME'] == 'gcc':
obj.cppflags.append('-fno-default-inline')
obj = bld(features='cxx cxxprogram')
obj.name = 'rewrite_subs'
- obj.uselib = 'BOOST_TEST BOOST_FILESYSTEM OPENJPEG CXML OPENMP ASDCPLIB_DCPOMATIC XMLSEC1 OPENSSL DL LIBXML++'
+ obj.uselib = 'BOOST_TEST BOOST_FILESYSTEM OPENJPEG CXML OPENMP ASDCPLIB_DCPOMATIC XMLSEC1 OPENSSL DL LIBXML++ AVCODEC AVUTIL'
obj.cppflags = ['-fno-inline', '-fno-elide-constructors', '-g', '-O0']
if bld.env['CXX_NAME'] == 'gcc':
obj.cppflags.append('-fno-default-inline')
#
def build(bld):
- uselib = 'OPENJPEG CXML OPENMP ASDCPLIB_DCPOMATIC BOOST_FILESYSTEM LIBXML++ XMLSEC1 OPENSSL XERCES DL MAGICK'
+ uselib = 'OPENJPEG CXML OPENMP ASDCPLIB_DCPOMATIC BOOST_FILESYSTEM LIBXML++ XMLSEC1 OPENSSL XERCES DL MAGICK AVCODEC AVUTIL'
for f in ['diff', 'info', 'verify']:
obj = bld(features='cxx cxxprogram')
lib=['boost_date_time%s' % boost_lib_suffix, 'boost_system%s' % boost_lib_suffix],
uselib_store='BOOST_DATETIME')
+ conf.check_cfg(package='libavcodec', args='--cflags --libs', uselib_store='AVCODEC', mandatory=True)
+ conf.check_cfg(package='libavutil', args='--cflags --libs', uselib_store='AVUTIL', mandatory=True)
+
if not conf.env.DISABLE_TESTS:
conf.recurse('test')
if conf.options.enable_gcov: