std::shared_ptr<const F> get_frame (int n) const
{
/* Can't use make_shared here as the constructor is private */
- return std::shared_ptr<const F> (new F(_reader, n, _crypto_context));
+ return std::shared_ptr<const F> (new F(_reader, n, _crypto_context, _check_hmac));
}
R* reader () const {
return _reader;
}
+ void set_check_hmac (bool check) {
+ _check_hmac = check;
+ }
+
protected:
R* _reader = nullptr;
std::shared_ptr<DecryptionContext> _crypto_context;
boost::throw_exception (FileError("could not open MXF file for reading", asset->file().get(), r));
}
}
+
+ bool _check_hmac = true;
};
class Frame
{
public:
- Frame (R* reader, int n, std::shared_ptr<const DecryptionContext> c)
+ Frame (R* reader, int n, std::shared_ptr<const DecryptionContext> c, bool check_hmac)
{
/* XXX: unfortunate guesswork on this buffer size */
_buffer = std::make_shared<B>(Kumu::Megabyte);
- if (ASDCP_FAILURE(reader->ReadFrame(n, *_buffer, c->context(), c->hmac()))) {
+ if (ASDCP_FAILURE(reader->ReadFrame(n, *_buffer, c->context(), check_hmac ? c->hmac() : nullptr))) {
boost::throw_exception (ReadError ("could not read frame"));
}
}
* @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.
*/
-MonoPictureFrame::MonoPictureFrame (ASDCP::JP2K::MXFReader* reader, int n, shared_ptr<DecryptionContext> c)
+MonoPictureFrame::MonoPictureFrame (ASDCP::JP2K::MXFReader* reader, int n, shared_ptr<DecryptionContext> c, bool check_hmac)
{
/* XXX: unfortunate guesswork on this buffer size */
_buffer = make_shared<ASDCP::JP2K::FrameBuffer>(4 * Kumu::Megabyte);
- auto const r = reader->ReadFrame (n, *_buffer, c->context(), c->hmac());
+ auto const r = reader->ReadFrame (n, *_buffer, c->context(), check_hmac ? c->hmac() : nullptr);
if (ASDCP_FAILURE(r)) {
boost::throw_exception (ReadError(String::compose ("could not read video frame %1 (%2)", n, static_cast<int>(r))));
*/
friend class AssetReader<ASDCP::JP2K::MXFReader, MonoPictureFrame>;
- MonoPictureFrame (ASDCP::JP2K::MXFReader* reader, int n, std::shared_ptr<DecryptionContext>);
+ MonoPictureFrame (ASDCP::JP2K::MXFReader* reader, int n, std::shared_ptr<DecryptionContext>, bool check_hmac);
std::shared_ptr<ASDCP::JP2K::FrameBuffer> _buffer;
};
using namespace dcp;
-SoundFrame::SoundFrame (ASDCP::PCM::MXFReader* reader, int n, std::shared_ptr<const DecryptionContext> c)
- : Frame<ASDCP::PCM::MXFReader, ASDCP::PCM::FrameBuffer> (reader, n, c)
+SoundFrame::SoundFrame (ASDCP::PCM::MXFReader* reader, int n, std::shared_ptr<const DecryptionContext> c, bool check_hmac)
+ : Frame<ASDCP::PCM::MXFReader, ASDCP::PCM::FrameBuffer> (reader, n, c, check_hmac)
{
ASDCP::PCM::AudioDescriptor desc;
reader->FillAudioDescriptor (desc);
class SoundFrame : public Frame<ASDCP::PCM::MXFReader, ASDCP::PCM::FrameBuffer>
{
public:
- SoundFrame (ASDCP::PCM::MXFReader* reader, int n, std::shared_ptr<const DecryptionContext> c);
+ SoundFrame (ASDCP::PCM::MXFReader* reader, int n, std::shared_ptr<const DecryptionContext> c, bool check_hmac);
int channels () const;
int samples () const;
int32_t get (int channel, int sample) const;
/** Make a picture frame from a 3D (stereoscopic) asset.
* @param reader Reader for the MXF file.
* @param n Frame within the asset, not taking EntryPoint into account.
+ * @param check_hmac true to check the HMAC and give an error if it is not as expected.
*/
-StereoPictureFrame::StereoPictureFrame (ASDCP::JP2K::MXFSReader* reader, int n, shared_ptr<DecryptionContext> c)
+StereoPictureFrame::StereoPictureFrame (ASDCP::JP2K::MXFSReader* reader, int n, shared_ptr<DecryptionContext> c, bool check_hmac)
{
/* XXX: unfortunate guesswork on this buffer size */
_buffer = make_shared<ASDCP::JP2K::SFrameBuffer>(4 * Kumu::Megabyte);
- if (ASDCP_FAILURE (reader->ReadFrame (n, *_buffer, c->context(), c->hmac()))) {
+ if (ASDCP_FAILURE (reader->ReadFrame (n, *_buffer, c->context(), check_hmac ? c->hmac() : nullptr))) {
boost::throw_exception (ReadError (String::compose ("could not read video frame %1 of %2", n)));
}
}
*/
friend class AssetReader<ASDCP::JP2K::MXFSReader, StereoPictureFrame>;
- StereoPictureFrame (ASDCP::JP2K::MXFSReader* reader, int n, std::shared_ptr<DecryptionContext>);
+ StereoPictureFrame (ASDCP::JP2K::MXFSReader* reader, int n, std::shared_ptr<DecryptionContext>, bool check_hmac);
std::shared_ptr<ASDCP::JP2K::SFrameBuffer> _buffer;
};
<< " -o, --output output filename\n"
<< " -k, --kdm KDM file\n"
<< " -p, --private-key private key file\n"
- << " -t, --type MXF type: picture or atmos\n";
+ << " -t, --type MXF type: picture or atmos\n"
+ << " -i, --ignore-hmac don't raise an error if HMACs don't agree\n";
}
template <class T, class U>
-void copy (T const& in, shared_ptr<U> writer)
+void copy (T const& in, shared_ptr<U> writer, bool ignore_hmac)
{
auto reader = in.start_read();
+ reader->set_check_hmac (!ignore_hmac);
for (int64_t i = 0; i < in.intrinsic_duration(); ++i) {
auto frame = reader->get_frame (i);
writer->write (frame->data(), frame->size());
optional<boost::filesystem::path> output_file;
optional<boost::filesystem::path> kdm_file;
optional<boost::filesystem::path> private_key_file;
+ bool ignore_hmac = false;
enum class Type {
PICTURE,
{ "kdm", required_argument, 0, 'k'},
{ "private-key", required_argument, 0, 'p'},
{ "type", required_argument, 0, 't' },
+ { "ignore-hmac", no_argument, 0, 'i' },
{ 0, 0, 0, 0 }
};
- int c = getopt_long (argc, argv, "Avho:k:p:t:", long_options, &option_index);
+ int c = getopt_long (argc, argv, "Avho:k:p:t:i", long_options, &option_index);
if (c == -1) {
break;
exit (EXIT_FAILURE);
}
break;
+ case 'i':
+ ignore_hmac = true;
+ break;
}
}
in.atmos_version()
);
auto writer = out.start_write (output_file.get());
- copy (in, writer);
+ copy (in, writer, ignore_hmac);
break;
}
case Type::PICTURE:
add_key (in, decrypted_kdm);
dcp::MonoPictureAsset out (in.edit_rate(), dcp::Standard::SMPTE);
auto writer = out.start_write (output_file.get(), false);
- copy (in, writer);
+ copy (in, writer, ignore_hmac);
break;
}
}