You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
398 lines
10 KiB
398 lines
10 KiB
/*****************************************************************************
|
|
* Copyright (C) 2013 VLC authors and VideoLAN
|
|
*
|
|
* Authors: Nicolas Bertrand <nico@isf.cc>
|
|
* Jean-Baptiste Kempf <jb@videolan.org>
|
|
* Guillaume Gonnaud
|
|
* Valentin Vetter <vvetter@outlook.com>
|
|
* Anthony Giniers
|
|
* Ludovic Hoareau
|
|
* Loukmane Dessai
|
|
* Simona-Marinela Prodea <simona dot marinela dot prodea at gmail dot com>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU Lesser General Public License as published by
|
|
* the Free Software Foundation; either version 2.1 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program 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 Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public License
|
|
* along with this program; if not, write to the Free Software Foundation,
|
|
* Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
|
|
*****************************************************************************/
|
|
|
|
/**
|
|
* @file dcpparser.h
|
|
* @brief Parse DCP XML files
|
|
*/
|
|
|
|
|
|
#ifndef VLC_DCP_DCPPARSER_H_
|
|
#define VLC_DCP_DCPPARSER_H_
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include "config.h"
|
|
#endif
|
|
|
|
/* VLC core API headers */
|
|
#include <vlc_common.h>
|
|
#include <vlc_arrays.h>
|
|
#include <vlc_demux.h>
|
|
#include <vlc_plugin.h>
|
|
|
|
/* gcrypt headers */
|
|
#include <gcrypt.h>
|
|
#include <vlc_gcrypt.h>
|
|
|
|
#include <iostream>
|
|
#include <string>
|
|
#include <list>
|
|
#include <vector>
|
|
|
|
using namespace std;
|
|
typedef enum {
|
|
TRACK_UNKNOWN = 0,
|
|
TRACK_PICTURE,
|
|
TRACK_SOUND,
|
|
TRACK_SUBTITLE
|
|
} TrackType_t;
|
|
|
|
class Asset;
|
|
class AssetList: public std::list<Asset *> {};
|
|
class PKL;
|
|
class AESKey;
|
|
class AESKeyList: public std::list<AESKey *> {};
|
|
|
|
/* This struct stores useful information about an MXF for demux() */
|
|
struct info_reel
|
|
{
|
|
string filename;
|
|
int i_entrypoint;
|
|
int i_duration;
|
|
int i_correction; /* entrypoint - sum of previous durations */
|
|
uint32_t i_absolute_end; /* correction + duration */
|
|
AESKey * p_key;
|
|
};
|
|
|
|
/* This struct stores the most important information about the DCP */
|
|
struct dcp_t
|
|
{
|
|
string path; /* Path to DCP directory */
|
|
|
|
vector<PKL *> pkls;
|
|
AssetList *p_asset_list;
|
|
AESKeyList *p_key_list;
|
|
|
|
vector<info_reel> audio_reels;
|
|
vector<info_reel> video_reels;
|
|
|
|
dcp_t():
|
|
p_asset_list(NULL), p_key_list(NULL) {};
|
|
|
|
~dcp_t( ) {
|
|
vlc_delete_all(pkls);
|
|
if ( p_asset_list != NULL ) {
|
|
vlc_delete_all(*p_asset_list);
|
|
delete(p_asset_list);
|
|
|
|
}
|
|
if ( p_key_list != NULL ) {
|
|
vlc_delete_all(*p_key_list);
|
|
delete(p_key_list);
|
|
}
|
|
}
|
|
};
|
|
|
|
class XmlFile
|
|
{
|
|
public:
|
|
XmlFile( demux_t * p_demux, string s_path):
|
|
p_demux(p_demux), s_path(s_path),
|
|
p_stream(NULL),
|
|
p_xmlReader(NULL) {}
|
|
|
|
virtual ~XmlFile( );
|
|
|
|
virtual int Parse() = 0;
|
|
|
|
static int ReadNextNode( demux_t *p_demux, xml_reader_t *p_xmlReader, string& s_node );
|
|
static int ReadEndNode( demux_t *p_demux, xml_reader_t *p_xmlReader, string s_node, int i_type, string &s_value );
|
|
|
|
int isCPL();
|
|
protected:
|
|
demux_t *p_demux;
|
|
string s_path;
|
|
stream_t *p_stream;
|
|
|
|
xml_reader_t *p_xmlReader;
|
|
|
|
int OpenXml();
|
|
void CloseXml();
|
|
};
|
|
|
|
class Chunk {
|
|
public:
|
|
Chunk(demux_t * demux):
|
|
i_vol_index(1), i_offset(0), i_length(0),
|
|
p_demux(demux) {};
|
|
int Parse(xml_reader_t *p_xmlReader, string p_node, int p_type);
|
|
string getPath() { return this->s_path; };
|
|
private:
|
|
string s_path;
|
|
int i_vol_index;
|
|
int i_offset;
|
|
int i_length;
|
|
demux_t *p_demux;
|
|
};
|
|
|
|
class Asset {
|
|
public:
|
|
/* Constructor */
|
|
Asset (demux_t * demux):
|
|
b_is_packing_list(false), ui_size(0),
|
|
i_intrisic_duration(0), i_entry_point(0), i_duration(0),
|
|
p_demux(demux) {}
|
|
virtual ~Asset() ;
|
|
|
|
void setId(string p_string ) { this->s_id = p_string; };
|
|
void setPath(string p_string) { this->s_path = p_string; };
|
|
void setAnnotation(string p_string) {
|
|
if (this->s_annotation.empty())
|
|
this->s_annotation = p_string;
|
|
else
|
|
this->s_annotation = this->s_annotation + "--" + p_string;
|
|
};
|
|
void setKeyId(string p_string) { this->s_key_id = p_string; };
|
|
void setPackingList(bool p_bool) { this->s_path = p_bool; };
|
|
void setEntryPoint(int i_val) { this->i_entry_point = i_val; };
|
|
void setDuration (int i_val) { this->i_duration = i_val; };
|
|
void setIntrinsicDuration (int i_val) { this->i_intrisic_duration = i_val; };
|
|
string getId() const { return this->s_id; } ;
|
|
string getPath() const { return this->s_path; };
|
|
string getType() const { return this->s_type; };
|
|
string getOriginalFilename() const { return this->s_original_filename; };
|
|
string getKeyId() const { return this->s_key_id; }
|
|
int getEntryPoint() const { return this->i_entry_point; };
|
|
int getDuration() const { return this->i_duration; };
|
|
int getIntrinsicDuration() const { return this->i_intrisic_duration; };
|
|
|
|
bool isPackingList() const { return this->b_is_packing_list; };
|
|
|
|
int Parse( xml_reader_t *p_xmlReader, string node, int type);
|
|
int ParsePKL( xml_reader_t *p_xmlReader);
|
|
|
|
static AESKey * getAESKeyById( AESKeyList* , const string s_id );
|
|
|
|
// TODO: remove
|
|
void Dump();
|
|
|
|
private:
|
|
string s_id;
|
|
string s_path;
|
|
string s_annotation;
|
|
bool b_is_packing_list;
|
|
string s_hash;
|
|
uint32_t ui_size;
|
|
string s_type;
|
|
string s_original_filename;
|
|
string s_edit_rate;
|
|
int i_intrisic_duration;
|
|
int i_entry_point;
|
|
int i_duration;
|
|
/* encryption attribute */
|
|
string s_key_id;
|
|
/* Picture attributes */
|
|
string s_frame_rate;
|
|
string s_screen_aspect_ratio;
|
|
/* sound and subtitle */
|
|
string s_language;
|
|
|
|
demux_t *p_demux;
|
|
std::vector<Chunk> chunk_vec;
|
|
|
|
|
|
int parseChunkList( xml_reader_t *p_xmlReader, string p_node, int p_type);
|
|
|
|
};
|
|
|
|
|
|
|
|
class Reel
|
|
{
|
|
public:
|
|
Reel(demux_t * demux, AssetList *asset_list, xml_reader_t *xmlReader)
|
|
: p_asset_list(asset_list), p_xmlReader(xmlReader), p_demux(demux), p_picture_track(NULL), p_sound_track(NULL), p_subtitle_track(NULL)
|
|
{};
|
|
int Parse(string p_node, int p_type);
|
|
Asset * getTrack(TrackType_t e_track);
|
|
|
|
private:
|
|
AssetList *p_asset_list;
|
|
xml_reader_t *p_xmlReader;
|
|
demux_t *p_demux;
|
|
|
|
string s_id;
|
|
string s_annotation;
|
|
Asset *p_picture_track;
|
|
Asset *p_sound_track;
|
|
Asset *p_subtitle_track;
|
|
|
|
int ParseAssetList(string p_node, int p_type);
|
|
int ParseAsset(string p_node, int p_type, TrackType_t e_track);
|
|
};
|
|
|
|
class CPL : public XmlFile
|
|
{
|
|
public:
|
|
CPL(demux_t * p_demux, string s_path, AssetList *_asset_list)
|
|
: XmlFile(p_demux, s_path), asset_list( _asset_list)
|
|
{};
|
|
~CPL();
|
|
virtual int Parse();
|
|
|
|
Reel *getReel(int pos) { return this->vec_reel[pos]; } ;
|
|
std::vector<Reel *> getReelList() { return this->vec_reel; } ;
|
|
|
|
private :
|
|
AssetList *asset_list;
|
|
|
|
string s_id;
|
|
string s_annotation;
|
|
string s_icon_id;
|
|
string s_issue_date;
|
|
string s_issuer;
|
|
string s_creator;
|
|
string s_content_title;
|
|
string s_content_kind;
|
|
/* TODO: ContentVersion, RatingList, signer and signature */
|
|
|
|
std::vector<Reel *> vec_reel;
|
|
int DummyParse(string p_node, int p_type);
|
|
int ParseReelList(string p_node, int p_type);
|
|
};
|
|
|
|
|
|
class PKL : public XmlFile
|
|
{
|
|
public:
|
|
PKL( demux_t * p_demux, string s_path, AssetList *_asset_list, string s )
|
|
: XmlFile( p_demux, s_path ), asset_list( _asset_list ), s_dcp_path( s )
|
|
{};
|
|
~PKL();
|
|
virtual int Parse();
|
|
|
|
int FindCPLs();
|
|
CPL *getCPL(int pos) { return this->vec_cpl[pos]; };
|
|
|
|
private:
|
|
AssetList *asset_list;
|
|
|
|
string s_id;
|
|
string s_annotation;
|
|
string s_issue_date;
|
|
string s_issuer;
|
|
string s_creator;
|
|
string s_icon_id;
|
|
string s_group_id;
|
|
string s_dcp_path;
|
|
std::vector<CPL *> vec_cpl;
|
|
|
|
int ParseAssetList(string p_node, int p_type);
|
|
int ParseAsset(string p_node, int p_type);
|
|
int ParseSigner(string p_node, int p_type);
|
|
int ParseSignature(string p_node, int p_type);
|
|
|
|
};
|
|
|
|
class AssetMap : public XmlFile {
|
|
|
|
public:
|
|
AssetMap( demux_t * p_demux, string s_path, dcp_t *_p_dcp)
|
|
: XmlFile( p_demux, s_path ), p_dcp( _p_dcp) {};
|
|
~AssetMap();
|
|
|
|
static Asset * getAssetById(AssetList*, const string p_id);
|
|
|
|
virtual int Parse();
|
|
private:
|
|
dcp_t *p_dcp;
|
|
|
|
int ParseAssetList (xml_reader_t *p_xmlReader, const string p_node, int p_type);
|
|
};
|
|
|
|
class KDM : public XmlFile {
|
|
|
|
public:
|
|
KDM( demux_t * p_demux, string s_path, dcp_t *_p_dcp )
|
|
: XmlFile( p_demux, s_path ), p_dcp(_p_dcp) {}
|
|
|
|
virtual int Parse();
|
|
|
|
private:
|
|
dcp_t *p_dcp;
|
|
|
|
int ParsePrivate( const string s_node, int i_type );
|
|
};
|
|
|
|
class AESKey
|
|
{
|
|
public:
|
|
AESKey( demux_t *demux ): p_demux( demux ) { }
|
|
virtual ~AESKey() {};
|
|
|
|
const string getKeyId() { return this->s_key_id; };
|
|
const unsigned char * getKey() { return this->ps_key; };
|
|
|
|
int Parse( xml_reader_t *p_xml_reader, string s_node, int i_type );
|
|
|
|
private:
|
|
demux_t *p_demux;
|
|
string s_key_id;
|
|
unsigned char ps_key[16];
|
|
|
|
int decryptRSA( string s_cipher_text_b64 );
|
|
int extractInfo( unsigned char * ps_plain_text, bool smpte );
|
|
};
|
|
|
|
class RSAKey
|
|
{
|
|
public:
|
|
RSAKey( demux_t *demux ):
|
|
priv_key( NULL ), p_demux( demux ) { }
|
|
virtual ~RSAKey() { gcry_sexp_release( priv_key ); }
|
|
|
|
/* some ASN.1 tags. */
|
|
enum
|
|
{
|
|
TAG_INTEGER = 2,
|
|
TAG_SEQUENCE = 16,
|
|
};
|
|
|
|
/* ASN.1 Parser object. */
|
|
struct tag_info
|
|
{
|
|
int class_; /* Object class. */
|
|
unsigned long tag; /* The tag of the object. */
|
|
unsigned long length; /* Length of the values. */
|
|
int nhdr; /* Length of the header (TL). */
|
|
unsigned int ndef:1; /* The object has an indefinite length. */
|
|
unsigned int cons:1; /* This is a constructed object. */
|
|
};
|
|
|
|
int setPath();
|
|
int readPEM();
|
|
int readDER( unsigned char const *ps_data_der, size_t length );
|
|
int parseTag( unsigned char const **buffer, size_t *buflen, struct tag_info *ti);
|
|
|
|
gcry_sexp_t priv_key;
|
|
|
|
private:
|
|
demux_t *p_demux;
|
|
string s_path;
|
|
};
|
|
|
|
#endif /* include-guard */
|
|
|