mirror of https://github.com/mpv-player/mpv
Added support for additional content encoding (compression, encryption) in general and zlib compression in particular (to be used with VobSubs).
git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@11230 b3059339-0415-0410-9bf9-f77b7e298cf2
This commit is contained in:
parent
2d0a6214d3
commit
7f54293847
|
@ -19,12 +19,17 @@ extern "C" {
|
||||||
#include <ebml/EbmlVersion.h>
|
#include <ebml/EbmlVersion.h>
|
||||||
#include <ebml/StdIOCallback.h>
|
#include <ebml/StdIOCallback.h>
|
||||||
|
|
||||||
|
#include <matroska/KaxVersion.h>
|
||||||
|
|
||||||
#include <matroska/KaxAttachments.h>
|
#include <matroska/KaxAttachments.h>
|
||||||
#include <matroska/KaxBlock.h>
|
#include <matroska/KaxBlock.h>
|
||||||
#include <matroska/KaxBlockData.h>
|
#include <matroska/KaxBlockData.h>
|
||||||
#include <matroska/KaxChapters.h>
|
#include <matroska/KaxChapters.h>
|
||||||
#include <matroska/KaxCluster.h>
|
#include <matroska/KaxCluster.h>
|
||||||
#include <matroska/KaxClusterData.h>
|
#include <matroska/KaxClusterData.h>
|
||||||
|
#if LIBMATROSKA_VERSION >= 000503
|
||||||
|
#include <matroska/KaxContentEncoding.h>
|
||||||
|
#endif
|
||||||
#include <matroska/KaxContexts.h>
|
#include <matroska/KaxContexts.h>
|
||||||
#include <matroska/KaxCues.h>
|
#include <matroska/KaxCues.h>
|
||||||
#include <matroska/KaxCuesData.h>
|
#include <matroska/KaxCuesData.h>
|
||||||
|
@ -44,6 +49,10 @@ extern "C" {
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_ZLIB
|
||||||
|
#include <zlib.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "../mp_msg.h"
|
#include "../mp_msg.h"
|
||||||
#include "../help_mp.h"
|
#include "../help_mp.h"
|
||||||
#include "stream.h"
|
#include "stream.h"
|
||||||
|
@ -61,10 +70,6 @@ using namespace libebml;
|
||||||
using namespace libmatroska;
|
using namespace libmatroska;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
#ifndef LIBEBML_VERSION
|
|
||||||
#define LIBEBML_VERSION 000000
|
|
||||||
#endif // LIBEBML_VERSION
|
|
||||||
|
|
||||||
#if LIBEBML_VERSION < 000500
|
#if LIBEBML_VERSION < 000500
|
||||||
#error libebml version too old - need at least 0.5.0
|
#error libebml version too old - need at least 0.5.0
|
||||||
#endif
|
#endif
|
||||||
|
@ -83,6 +88,29 @@ extern char *audio_lang;
|
||||||
#define MKV_SUBCOMPRESSION_NONE 0
|
#define MKV_SUBCOMPRESSION_NONE 0
|
||||||
#define MKV_SUBCOMPRESSION_ZLIB 1
|
#define MKV_SUBCOMPRESSION_ZLIB 1
|
||||||
|
|
||||||
|
#define safefree(m) { if (m != NULL) free(m); }
|
||||||
|
void *safemalloc(int bytes) {
|
||||||
|
void *dst;
|
||||||
|
|
||||||
|
dst = malloc(bytes);
|
||||||
|
if (dst == NULL) {
|
||||||
|
mp_msg(MSGT_DEMUX, MSGL_FATAL, "[mkv] Could not allocate %d bytes of "
|
||||||
|
"memory.\n", bytes);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return dst;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *safememdup(const void *src, int bytes) {
|
||||||
|
void *dst;
|
||||||
|
|
||||||
|
dst = safemalloc(bytes);
|
||||||
|
memcpy(dst, src, bytes);
|
||||||
|
|
||||||
|
return dst;
|
||||||
|
}
|
||||||
|
|
||||||
class mpstream_io_callback: public IOCallback {
|
class mpstream_io_callback: public IOCallback {
|
||||||
private:
|
private:
|
||||||
stream_t *s;
|
stream_t *s;
|
||||||
|
@ -149,6 +177,16 @@ typedef struct mkv_track_index {
|
||||||
mkv_index_entry_t *entries;
|
mkv_index_entry_t *entries;
|
||||||
} mkv_track_index_t;
|
} mkv_track_index_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint32_t order, type, scope;
|
||||||
|
uint32_t comp_algo;
|
||||||
|
unsigned char *comp_settings;
|
||||||
|
uint32_t comp_settings_len;
|
||||||
|
uint32_t enc_algo, sig_algo, sig_hash_algo;
|
||||||
|
unsigned char *enc_keyid, *sig_keyid, *signature;
|
||||||
|
uint32_t enc_keyid_len, sig_keyid_len, signature_len;
|
||||||
|
} mkv_content_encoding_t;
|
||||||
|
|
||||||
typedef struct mkv_track {
|
typedef struct mkv_track {
|
||||||
uint32_t tnum, xid;
|
uint32_t tnum, xid;
|
||||||
|
|
||||||
|
@ -190,7 +228,13 @@ typedef struct mkv_track {
|
||||||
|
|
||||||
// Stuff for VobSubs
|
// Stuff for VobSubs
|
||||||
mkv_sh_sub_t sh_sub;
|
mkv_sh_sub_t sh_sub;
|
||||||
int vobsub_compression;
|
|
||||||
|
// Generic content encoding support.
|
||||||
|
vector<mkv_content_encoding_t> *c_encodings;
|
||||||
|
#ifdef HAVE_ZLIB
|
||||||
|
z_stream zstream;
|
||||||
|
bool zstream_initiated;
|
||||||
|
#endif
|
||||||
} mkv_track_t;
|
} mkv_track_t;
|
||||||
|
|
||||||
typedef struct mkv_demuxer {
|
typedef struct mkv_demuxer {
|
||||||
|
@ -531,22 +575,22 @@ static void handle_subtitles(demuxer_t *d, KaxBlock *block, int64_t duration) {
|
||||||
static mkv_track_t *new_mkv_track(mkv_demuxer_t *d) {
|
static mkv_track_t *new_mkv_track(mkv_demuxer_t *d) {
|
||||||
mkv_track_t *t;
|
mkv_track_t *t;
|
||||||
|
|
||||||
t = (mkv_track_t *)malloc(sizeof(mkv_track_t));
|
t = (mkv_track_t *)safemalloc(sizeof(mkv_track_t));
|
||||||
if (t != NULL) {
|
memset(t, 0, sizeof(mkv_track_t));
|
||||||
memset(t, 0, sizeof(mkv_track_t));
|
d->tracks = (mkv_track_t **)realloc(d->tracks, (d->num_tracks + 1) *
|
||||||
d->tracks = (mkv_track_t **)realloc(d->tracks, (d->num_tracks + 1) *
|
sizeof(mkv_track_t *));
|
||||||
sizeof(mkv_track_t *));
|
if (d->tracks == NULL)
|
||||||
if (d->tracks == NULL)
|
return NULL;
|
||||||
return NULL;
|
d->tracks[d->num_tracks] = t;
|
||||||
d->tracks[d->num_tracks] = t;
|
d->num_tracks++;
|
||||||
d->num_tracks++;
|
|
||||||
|
|
||||||
// Set default values.
|
// Set default values.
|
||||||
t->default_track = 1;
|
t->default_track = 1;
|
||||||
t->a_sfreq = 8000.0;
|
t->a_sfreq = 8000.0;
|
||||||
t->a_channels = 1;
|
t->a_channels = 1;
|
||||||
t->language = strdup("eng");
|
t->language = strdup("eng");
|
||||||
}
|
|
||||||
|
t->c_encodings = new vector<mkv_content_encoding_t>;
|
||||||
|
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
@ -657,17 +701,132 @@ static bool mkv_parse_idx(mkv_track_t *t) {
|
||||||
return (things_found == 3);
|
return (things_found == 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool reverse_encodings(mkv_track_t *track, unsigned char *&data,
|
||||||
|
uint32_t &size, uint32_t type) {
|
||||||
|
int new_size;
|
||||||
|
unsigned char *new_data, *old_data;
|
||||||
|
bool modified;
|
||||||
|
vector<mkv_content_encoding_t>::iterator ce;
|
||||||
|
|
||||||
|
if (track->c_encodings->size() == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
new_data = data;
|
||||||
|
new_size = size;
|
||||||
|
modified = false;
|
||||||
|
for (ce = track->c_encodings->begin(); ce < track->c_encodings->end();
|
||||||
|
ce++) {
|
||||||
|
if ((ce->scope & type) == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
#ifdef HAVE_ZLIB
|
||||||
|
if (ce->comp_algo == 0) {
|
||||||
|
int result;
|
||||||
|
|
||||||
|
old_data = new_data;
|
||||||
|
new_data = (unsigned char *)safemalloc(new_size * 20);
|
||||||
|
|
||||||
|
track->zstream.next_in = (Bytef *)old_data;
|
||||||
|
track->zstream.next_out = (Bytef *)new_data;
|
||||||
|
track->zstream.avail_in = new_size;
|
||||||
|
track->zstream.avail_out = 20 * new_size;
|
||||||
|
result = inflate(&track->zstream, Z_FULL_FLUSH);
|
||||||
|
if (result != Z_OK) {
|
||||||
|
mp_msg(MSGT_DEMUX, MSGL_WARN, "[mkv] Zlib decompression failed. "
|
||||||
|
"Result: %d\n", result);
|
||||||
|
safefree(new_data);
|
||||||
|
data = old_data;
|
||||||
|
size = new_size;
|
||||||
|
return modified;
|
||||||
|
}
|
||||||
|
|
||||||
|
mp_msg(MSGT_DEMUX, MSGL_DBG2, "[mkv] zlib decompression: from %d to "
|
||||||
|
"%d\n", new_size, 20 * new_size - track->zstream.avail_out);
|
||||||
|
new_size = 20 * new_size - track->zstream.avail_out;
|
||||||
|
|
||||||
|
if (modified)
|
||||||
|
safefree(old_data);
|
||||||
|
modified = true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
data = new_data;
|
||||||
|
size = new_size;
|
||||||
|
|
||||||
|
return modified;
|
||||||
|
}
|
||||||
|
|
||||||
static int check_track_information(mkv_demuxer_t *d) {
|
static int check_track_information(mkv_demuxer_t *d) {
|
||||||
int i, track_num;
|
int i, track_num;
|
||||||
unsigned char *c;
|
unsigned char *c;
|
||||||
uint32_t u, offset, length;
|
uint32_t u, offset, length;
|
||||||
mkv_track_t *t;
|
mkv_track_t *t;
|
||||||
|
mkv_content_encoding_t *ce;
|
||||||
BITMAPINFOHEADER *bih;
|
BITMAPINFOHEADER *bih;
|
||||||
WAVEFORMATEX *wfe;
|
WAVEFORMATEX *wfe;
|
||||||
|
|
||||||
for (track_num = 0; track_num < d->num_tracks; track_num++) {
|
for (track_num = 0; track_num < d->num_tracks; track_num++) {
|
||||||
|
|
||||||
t = d->tracks[track_num];
|
t = d->tracks[track_num];
|
||||||
|
|
||||||
|
t->ok = 1;
|
||||||
|
for (i = 0; i < (int)t->c_encodings->size(); i++) {
|
||||||
|
ce = &(*t->c_encodings)[i];
|
||||||
|
|
||||||
|
if (ce->type == 1) {
|
||||||
|
mp_msg(MSGT_DEMUX, MSGL_WARN, "[mkv] Track number %u has been "
|
||||||
|
"encrypted and decryption has not yet been implemented. "
|
||||||
|
"Skipping track.\n", t->tnum);
|
||||||
|
t->ok = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ce->type != 0) {
|
||||||
|
mp_msg(MSGT_DEMUX, MSGL_WARN, "[mkv] Unknown content encoding type %u "
|
||||||
|
"for track %u. Skipping track.\n", ce->type, t->tnum);
|
||||||
|
t->ok = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ce->comp_algo == 0) {
|
||||||
|
#if !defined(HAVE_ZLIB)
|
||||||
|
mp_msg(MSGT_DEMUX, MSGL_WARN, "Track %u was compressed with zlib but "
|
||||||
|
"mplayer has not been compiled with support for zlib "
|
||||||
|
"compression. Skipping track.\n", t->tnum);
|
||||||
|
t->ok = 0;
|
||||||
|
break;
|
||||||
|
#else
|
||||||
|
if (!t->zstream_initiated) {
|
||||||
|
t->zstream.zalloc = (alloc_func)0;
|
||||||
|
t->zstream.zfree = (free_func)0;
|
||||||
|
t->zstream.opaque = (voidpf)0;
|
||||||
|
inflateInit(&t->zstream);
|
||||||
|
t->zstream_initiated = true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
mp_msg(MSGT_DEMUX, MSGL_WARN, "[mkv] Track %u has been compressed "
|
||||||
|
"with an unknown/unsupported compression algorithm (%u). "
|
||||||
|
"Skipping track.\n", t->tnum, ce->comp_algo);
|
||||||
|
t->ok = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!t->ok)
|
||||||
|
continue;
|
||||||
|
t->ok = 0;
|
||||||
|
|
||||||
|
if (t->private_data != NULL) {
|
||||||
|
c = (unsigned char *)t->private_data;
|
||||||
|
length = t->private_size;
|
||||||
|
if (reverse_encodings(t, c, length, 2)) {
|
||||||
|
safefree(t->private_data);
|
||||||
|
t->private_data = c;
|
||||||
|
t->private_size = length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
switch (t->type) {
|
switch (t->type) {
|
||||||
case 'v': // video track
|
case 'v': // video track
|
||||||
if (t->codec_id == NULL)
|
if (t->codec_id == NULL)
|
||||||
|
@ -888,7 +1047,7 @@ static int check_track_information(mkv_demuxer_t *d) {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 's':
|
case 's':
|
||||||
if (!strncmp(t->codec_id, MKV_S_VOBSUB, strlen(MKV_S_VOBSUB))) {
|
if (!strcmp(t->codec_id, MKV_S_VOBSUB)) {
|
||||||
if (mkv_parse_idx(t)) {
|
if (mkv_parse_idx(t)) {
|
||||||
t->ok = 1;
|
t->ok = 1;
|
||||||
mp_msg(MSGT_DEMUX, MSGL_INFO, "[mkv] Track ID %u: subtitles (%s), "
|
mp_msg(MSGT_DEMUX, MSGL_INFO, "[mkv] Track ID %u: subtitles (%s), "
|
||||||
|
@ -920,7 +1079,7 @@ static int check_track_information(mkv_demuxer_t *d) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void free_mkv_demuxer(mkv_demuxer_t *d) {
|
static void free_mkv_demuxer(mkv_demuxer_t *d) {
|
||||||
int i;
|
int i, k;
|
||||||
|
|
||||||
if (d == NULL)
|
if (d == NULL)
|
||||||
return;
|
return;
|
||||||
|
@ -931,6 +1090,17 @@ static void free_mkv_demuxer(mkv_demuxer_t *d) {
|
||||||
free(d->tracks[i]->private_data);
|
free(d->tracks[i]->private_data);
|
||||||
if (d->tracks[i]->language != NULL)
|
if (d->tracks[i]->language != NULL)
|
||||||
free(d->tracks[i]->language);
|
free(d->tracks[i]->language);
|
||||||
|
for (k = 0; k < (int)d->tracks[i]->c_encodings->size(); k++) {
|
||||||
|
safefree((*d->tracks[i]->c_encodings)[k].comp_settings);
|
||||||
|
safefree((*d->tracks[i]->c_encodings)[k].enc_keyid);
|
||||||
|
safefree((*d->tracks[i]->c_encodings)[k].sig_keyid);
|
||||||
|
safefree((*d->tracks[i]->c_encodings)[k].signature);
|
||||||
|
}
|
||||||
|
delete d->tracks[i]->c_encodings;
|
||||||
|
#ifdef HAVE_ZLIB
|
||||||
|
if (d->tracks[i]->zstream_initiated)
|
||||||
|
inflateEnd(&d->tracks[i]->zstream);
|
||||||
|
#endif
|
||||||
free(d->tracks[i]);
|
free(d->tracks[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1244,9 +1414,7 @@ extern "C" int demux_mkv_open(demuxer_t *demuxer) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// structure for storing the demuxer's private data
|
// structure for storing the demuxer's private data
|
||||||
mkv_d = (mkv_demuxer_t *)malloc(sizeof(mkv_demuxer_t));
|
mkv_d = (mkv_demuxer_t *)safemalloc(sizeof(mkv_demuxer_t));
|
||||||
if (mkv_d == NULL)
|
|
||||||
return 0;
|
|
||||||
memset(mkv_d, 0, sizeof(mkv_demuxer_t));
|
memset(mkv_d, 0, sizeof(mkv_demuxer_t));
|
||||||
mkv_d->duration = -1.0;
|
mkv_d->duration = -1.0;
|
||||||
|
|
||||||
|
@ -1356,6 +1524,11 @@ extern "C" int demux_mkv_open(demuxer_t *demuxer) {
|
||||||
KaxCodecPrivate *kcodecpriv;
|
KaxCodecPrivate *kcodecpriv;
|
||||||
KaxTrackFlagDefault *ktfdefault;
|
KaxTrackFlagDefault *ktfdefault;
|
||||||
KaxTrackLanguage *ktlanguage;
|
KaxTrackLanguage *ktlanguage;
|
||||||
|
#if LIBMATROSKA_VERSION >= 000503
|
||||||
|
KaxContentEncodings *kcencodings;
|
||||||
|
int kcenc_idx;
|
||||||
|
vector<mkv_content_encoding_t>::iterator ce_ins_it;
|
||||||
|
#endif
|
||||||
|
|
||||||
mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + a track...\n");
|
mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + a track...\n");
|
||||||
|
|
||||||
|
@ -1507,13 +1680,9 @@ extern "C" int demux_mkv_open(demuxer_t *demuxer) {
|
||||||
mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + CodecPrivate, length "
|
mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + CodecPrivate, length "
|
||||||
"%llu\n", kcodecpriv->GetSize());
|
"%llu\n", kcodecpriv->GetSize());
|
||||||
track->private_size = kcodecpriv->GetSize();
|
track->private_size = kcodecpriv->GetSize();
|
||||||
if (track->private_size > 0) {
|
if (track->private_size > 0)
|
||||||
track->private_data = malloc(track->private_size);
|
track->private_data = safememdup(kcodecpriv->GetBuffer(),
|
||||||
if (track->private_data == NULL)
|
track->private_size);
|
||||||
return 0;
|
|
||||||
memcpy(track->private_data, kcodecpriv->GetBuffer(),
|
|
||||||
track->private_size);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ktfdefault = FINDFIRST(ktentry, KaxTrackFlagDefault);
|
ktfdefault = FINDFIRST(ktentry, KaxTrackFlagDefault);
|
||||||
|
@ -1532,6 +1701,115 @@ extern "C" int demux_mkv_open(demuxer_t *demuxer) {
|
||||||
track->language = strdup(string(*ktlanguage).c_str());
|
track->language = strdup(string(*ktlanguage).c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if LIBMATROSKA_VERSION >= 000503
|
||||||
|
kcencodings = FINDFIRST(ktentry, KaxContentEncodings);
|
||||||
|
if (kcencodings != NULL) {
|
||||||
|
for (kcenc_idx = 0; kcenc_idx < (int)kcencodings->ListSize();
|
||||||
|
kcenc_idx++) {
|
||||||
|
EbmlElement *l3;
|
||||||
|
|
||||||
|
l3 = (*kcencodings)[kcenc_idx];
|
||||||
|
if (EbmlId(*l3) == KaxContentEncoding::ClassInfos.GlobalId) {
|
||||||
|
KaxContentEncoding *kcenc;
|
||||||
|
KaxContentEncodingOrder *ce_order;
|
||||||
|
KaxContentEncodingType *ce_type;
|
||||||
|
KaxContentEncodingScope *ce_scope;
|
||||||
|
KaxContentCompression *ce_comp;
|
||||||
|
KaxContentEncryption *ce_enc;
|
||||||
|
mkv_content_encoding_t enc;
|
||||||
|
|
||||||
|
memset(&enc, 0, sizeof(mkv_content_encoding_t));
|
||||||
|
kcenc = static_cast<KaxContentEncoding *>(l3);
|
||||||
|
|
||||||
|
ce_order = FINDFIRST(kcenc, KaxContentEncodingOrder);
|
||||||
|
if (ce_order != NULL)
|
||||||
|
enc.order = uint32(*ce_order);
|
||||||
|
|
||||||
|
ce_type = FINDFIRST(kcenc, KaxContentEncodingType);
|
||||||
|
if (ce_type != NULL)
|
||||||
|
enc.type = uint32(*ce_type);
|
||||||
|
|
||||||
|
ce_scope = FINDFIRST(kcenc, KaxContentEncodingScope);
|
||||||
|
if (ce_scope != NULL)
|
||||||
|
enc.scope = uint32(*ce_scope);
|
||||||
|
else
|
||||||
|
enc.scope = 1;
|
||||||
|
|
||||||
|
ce_comp = FINDFIRST(kcenc, KaxContentCompression);
|
||||||
|
if (ce_comp != NULL) {
|
||||||
|
KaxContentCompAlgo *cc_algo;
|
||||||
|
KaxContentCompSettings *cc_settings;
|
||||||
|
|
||||||
|
cc_algo = FINDFIRST(ce_comp, KaxContentCompAlgo);
|
||||||
|
if (cc_algo != NULL)
|
||||||
|
enc.comp_algo = uint32(*cc_algo);
|
||||||
|
|
||||||
|
cc_settings = FINDFIRST(ce_comp, KaxContentCompSettings);
|
||||||
|
if (cc_settings != NULL) {
|
||||||
|
enc.comp_settings =
|
||||||
|
(unsigned char *)safememdup(&binary(*cc_settings),
|
||||||
|
cc_settings->GetSize());
|
||||||
|
enc.comp_settings_len = cc_settings->GetSize();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ce_enc = FINDFIRST(kcenc, KaxContentEncryption);
|
||||||
|
if (ce_enc != NULL) {
|
||||||
|
KaxContentEncAlgo *ce_ealgo;
|
||||||
|
KaxContentEncKeyID *ce_ekeyid;
|
||||||
|
KaxContentSigAlgo *ce_salgo;
|
||||||
|
KaxContentSigHashAlgo *ce_shalgo;
|
||||||
|
KaxContentSigKeyID *ce_skeyid;
|
||||||
|
KaxContentSignature *ce_signature;
|
||||||
|
|
||||||
|
ce_ealgo = FINDFIRST(ce_enc, KaxContentEncAlgo);
|
||||||
|
if (ce_ealgo != NULL)
|
||||||
|
enc.enc_algo = uint32(*ce_ealgo);
|
||||||
|
|
||||||
|
ce_ekeyid = FINDFIRST(ce_enc, KaxContentEncKeyID);
|
||||||
|
if (ce_ekeyid != NULL) {
|
||||||
|
enc.enc_keyid =
|
||||||
|
(unsigned char *)safememdup(&binary(*ce_ekeyid),
|
||||||
|
ce_ekeyid->GetSize());
|
||||||
|
enc.enc_keyid_len = ce_ekeyid->GetSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
ce_salgo = FINDFIRST(ce_enc, KaxContentSigAlgo);
|
||||||
|
if (ce_salgo != NULL)
|
||||||
|
enc.enc_algo = uint32(*ce_salgo);
|
||||||
|
|
||||||
|
ce_shalgo = FINDFIRST(ce_enc, KaxContentSigHashAlgo);
|
||||||
|
if (ce_shalgo != NULL)
|
||||||
|
enc.enc_algo = uint32(*ce_shalgo);
|
||||||
|
|
||||||
|
ce_skeyid = FINDFIRST(ce_enc, KaxContentSigKeyID);
|
||||||
|
if (ce_skeyid != NULL) {
|
||||||
|
enc.sig_keyid =
|
||||||
|
(unsigned char *)safememdup(&binary(*ce_skeyid),
|
||||||
|
ce_skeyid->GetSize());
|
||||||
|
enc.sig_keyid_len = ce_skeyid->GetSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
ce_signature = FINDFIRST(ce_enc, KaxContentSignature);
|
||||||
|
if (ce_signature != NULL) {
|
||||||
|
enc.signature =
|
||||||
|
(unsigned char *)safememdup(&binary(*ce_signature),
|
||||||
|
ce_signature->GetSize());
|
||||||
|
enc.signature_len = ce_signature->GetSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ce_ins_it = track->c_encodings->begin();
|
||||||
|
while ((ce_ins_it != track->c_encodings->end()) &&
|
||||||
|
(enc.order <= (*ce_ins_it).order))
|
||||||
|
ce_ins_it++;
|
||||||
|
track->c_encodings->insert(ce_ins_it, enc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
ktentry = FINDNEXT(l1, KaxTrackEntry, ktentry);
|
ktentry = FINDNEXT(l1, KaxTrackEntry, ktentry);
|
||||||
} // while (ktentry != NULL)
|
} // while (ktentry != NULL)
|
||||||
|
|
||||||
|
@ -1650,11 +1928,8 @@ extern "C" int demux_mkv_open(demuxer_t *demuxer) {
|
||||||
BITMAPINFOHEADER *bih;
|
BITMAPINFOHEADER *bih;
|
||||||
|
|
||||||
idesc = NULL;
|
idesc = NULL;
|
||||||
bih = (BITMAPINFOHEADER *)calloc(1, track->private_size);
|
bih = (BITMAPINFOHEADER *)safemalloc(track->private_size);
|
||||||
if (bih == NULL) {
|
memset(bih, 0, sizeof(BITMAPINFOHEADER));
|
||||||
free_mkv_demuxer(mkv_d);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (track->ms_compat) { // MS compatibility mode
|
if (track->ms_compat) { // MS compatibility mode
|
||||||
BITMAPINFOHEADER *src;
|
BITMAPINFOHEADER *src;
|
||||||
|
@ -1816,19 +2091,12 @@ extern "C" int demux_mkv_open(demuxer_t *demuxer) {
|
||||||
|
|
||||||
mkv_d->audio = track;
|
mkv_d->audio = track;
|
||||||
|
|
||||||
if (track->ms_compat) {
|
if (track->ms_compat)
|
||||||
sh_a->wf = (WAVEFORMATEX *)calloc(1, track->private_size);
|
sh_a->wf = (WAVEFORMATEX *)safememdup(track->private_data,
|
||||||
if (sh_a->wf == NULL) {
|
track->private_size);
|
||||||
free_mkv_demuxer(mkv_d);
|
else {
|
||||||
return 0;
|
sh_a->wf = (WAVEFORMATEX *)safemalloc(sizeof(WAVEFORMATEX));
|
||||||
}
|
memset(sh_a->wf, 0, sizeof(WAVEFORMATEX));
|
||||||
memcpy(sh_a->wf, track->private_data, track->private_size);
|
|
||||||
} else {
|
|
||||||
sh_a->wf = (WAVEFORMATEX *)calloc(1, sizeof(WAVEFORMATEX));
|
|
||||||
if (sh_a->wf == NULL) {
|
|
||||||
free_mkv_demuxer(mkv_d);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
sh_a->format = track->a_formattag;
|
sh_a->format = track->a_formattag;
|
||||||
sh_a->wf->wFormatTag = track->a_formattag;
|
sh_a->wf->wFormatTag = track->a_formattag;
|
||||||
|
@ -1866,8 +2134,8 @@ extern "C" int demux_mkv_open(demuxer_t *demuxer) {
|
||||||
track->fix_i_bps = true;
|
track->fix_i_bps = true;
|
||||||
track->qt_last_a_pts = 0.0;
|
track->qt_last_a_pts = 0.0;
|
||||||
if (track->private_data != NULL) {
|
if (track->private_data != NULL) {
|
||||||
sh_a->codecdata = (unsigned char *)calloc(track->private_size, 1);
|
sh_a->codecdata = (unsigned char *)safememdup(track->private_data,
|
||||||
memcpy(sh_a->codecdata, track->private_data, track->private_size);
|
track->private_size);
|
||||||
sh_a->codecdata_len = track->private_size;
|
sh_a->codecdata_len = track->private_size;
|
||||||
}
|
}
|
||||||
if (!strcmp(track->codec_id, MKV_A_QDMC))
|
if (!strcmp(track->codec_id, MKV_A_QDMC))
|
||||||
|
@ -1919,7 +2187,7 @@ extern "C" int demux_mkv_open(demuxer_t *demuxer) {
|
||||||
else
|
else
|
||||||
srate_idx = 11;
|
srate_idx = 11;
|
||||||
|
|
||||||
sh_a->codecdata = (unsigned char *)calloc(1, 2);
|
sh_a->codecdata = (unsigned char *)safemalloc(2);
|
||||||
sh_a->codecdata_len = 2;
|
sh_a->codecdata_len = 2;
|
||||||
sh_a->codecdata[0] = ((profile + 1) << 3) | ((srate_idx & 0xe) >> 1);
|
sh_a->codecdata[0] = ((profile + 1) << 3) | ((srate_idx & 0xe) >> 1);
|
||||||
sh_a->codecdata[1] = ((srate_idx & 0x1) << 7) | (track->a_channels << 3);
|
sh_a->codecdata[1] = ((srate_idx & 0x1) << 7) | (track->a_channels << 3);
|
||||||
|
@ -1988,14 +2256,14 @@ extern "C" int demux_mkv_open(demuxer_t *demuxer) {
|
||||||
else if (dvdsub_lang != NULL)
|
else if (dvdsub_lang != NULL)
|
||||||
track = find_track_by_language(mkv_d, dvdsub_lang, NULL);
|
track = find_track_by_language(mkv_d, dvdsub_lang, NULL);
|
||||||
if (track) {
|
if (track) {
|
||||||
if (!strncmp(track->codec_id, MKV_S_VOBSUB, strlen(MKV_S_VOBSUB))) {
|
if (!strcmp(track->codec_id, MKV_S_VOBSUB)) {
|
||||||
mp_msg(MSGT_DEMUX, MSGL_INFO, "[mkv] Will display subtitle track %u\n",
|
mp_msg(MSGT_DEMUX, MSGL_INFO, "[mkv] Will display subtitle track %u\n",
|
||||||
track->tnum);
|
track->tnum);
|
||||||
mkv_d->subs_track = track;
|
mkv_d->subs_track = track;
|
||||||
mkv_d->subtitle_type = MKV_SUBTYPE_VOBSUB;
|
mkv_d->subtitle_type = MKV_SUBTYPE_VOBSUB;
|
||||||
demuxer->sub->sh = (mkv_sh_sub_t *)malloc(sizeof(mkv_sh_sub_t));
|
demuxer->sub->sh = (mkv_sh_sub_t *)safememdup(&track->sh_sub,
|
||||||
|
sizeof(mkv_sh_sub_t));
|
||||||
demuxer->sub->id = track->xid;
|
demuxer->sub->id = track->xid;
|
||||||
memcpy(demuxer->sub->sh, &track->sh_sub, sizeof(mkv_sh_sub_t));
|
|
||||||
|
|
||||||
} else if (strcmp(track->codec_id, MKV_S_TEXTASCII) &&
|
} else if (strcmp(track->codec_id, MKV_S_TEXTASCII) &&
|
||||||
strcmp(track->codec_id, MKV_S_TEXTUTF8) &&
|
strcmp(track->codec_id, MKV_S_TEXTUTF8) &&
|
||||||
|
@ -2009,7 +2277,7 @@ extern "C" int demux_mkv_open(demuxer_t *demuxer) {
|
||||||
mkv_d->subs_track = track;
|
mkv_d->subs_track = track;
|
||||||
if (!mkv_d->subs.text[0]) {
|
if (!mkv_d->subs.text[0]) {
|
||||||
for (i = 0; i < SUB_MAX_TEXT; i++)
|
for (i = 0; i < SUB_MAX_TEXT; i++)
|
||||||
mkv_d->subs.text[i] = (char *)malloc(256);
|
mkv_d->subs.text[i] = (char *)safemalloc(256);
|
||||||
|
|
||||||
if (!strcmp(track->codec_id, MKV_S_TEXTUTF8))
|
if (!strcmp(track->codec_id, MKV_S_TEXTUTF8))
|
||||||
sub_utf8 = 1; // Force UTF-8 conversion.
|
sub_utf8 = 1; // Force UTF-8 conversion.
|
||||||
|
@ -2095,9 +2363,8 @@ static float real_fix_timestamp(mkv_track_t *track, unsigned char *s,
|
||||||
return v_pts;
|
return v_pts;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_realvideo(demuxer_t *demuxer, DataBuffer &data,
|
static void handle_realvideo(demuxer_t *demuxer, unsigned char *data,
|
||||||
bool keyframe, int &found_data) {
|
uint32_t size, bool keyframe, int &found_data) {
|
||||||
unsigned char *p;
|
|
||||||
dp_hdr_t *hdr;
|
dp_hdr_t *hdr;
|
||||||
int chunks, isize;
|
int chunks, isize;
|
||||||
mkv_demuxer_t *mkv_d;
|
mkv_demuxer_t *mkv_d;
|
||||||
|
@ -2106,12 +2373,11 @@ static void handle_realvideo(demuxer_t *demuxer, DataBuffer &data,
|
||||||
|
|
||||||
mkv_d = (mkv_demuxer_t *)demuxer->priv;
|
mkv_d = (mkv_demuxer_t *)demuxer->priv;
|
||||||
ds = demuxer->video;
|
ds = demuxer->video;
|
||||||
p = (unsigned char *)data.Buffer();
|
chunks = data[0];
|
||||||
chunks = p[0];
|
isize = size - 1 - (chunks + 1) * 8;
|
||||||
isize = data.Size() - 1 - (chunks + 1) * 8;
|
|
||||||
dp = new_demux_packet(sizeof(dp_hdr_t) + isize + 8 * (chunks + 1));
|
dp = new_demux_packet(sizeof(dp_hdr_t) + isize + 8 * (chunks + 1));
|
||||||
memcpy(&dp->buffer[sizeof(dp_hdr_t)], &p[1 + (chunks + 1) * 8], isize);
|
memcpy(&dp->buffer[sizeof(dp_hdr_t)], &data[1 + (chunks + 1) * 8], isize);
|
||||||
memcpy(&dp->buffer[sizeof(dp_hdr_t) + isize], &p[1], (chunks + 1) * 8);
|
memcpy(&dp->buffer[sizeof(dp_hdr_t) + isize], &data[1], (chunks + 1) * 8);
|
||||||
hdr = (dp_hdr_t *)dp->buffer;
|
hdr = (dp_hdr_t *)dp->buffer;
|
||||||
hdr->len = isize;
|
hdr->len = isize;
|
||||||
hdr->chunks = chunks;
|
hdr->chunks = chunks;
|
||||||
|
@ -2134,15 +2400,15 @@ static void handle_realvideo(demuxer_t *demuxer, DataBuffer &data,
|
||||||
found_data++;
|
found_data++;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_realaudio(demuxer_t *demuxer, DataBuffer &data,
|
static void handle_realaudio(demuxer_t *demuxer, unsigned char *data,
|
||||||
bool keyframe, int &found_data) {
|
uint32_t size, bool keyframe, int &found_data) {
|
||||||
mkv_demuxer_t *mkv_d;
|
mkv_demuxer_t *mkv_d;
|
||||||
demux_packet_t *dp;
|
demux_packet_t *dp;
|
||||||
|
|
||||||
mkv_d = (mkv_demuxer_t *)demuxer->priv;
|
mkv_d = (mkv_demuxer_t *)demuxer->priv;
|
||||||
|
|
||||||
dp = new_demux_packet(data.Size());
|
dp = new_demux_packet(size);
|
||||||
memcpy(dp->buffer, data.Buffer(), data.Size());
|
memcpy(dp->buffer, data, size);
|
||||||
if ((mkv_d->audio->ra_pts == mkv_d->last_pts) &&
|
if ((mkv_d->audio->ra_pts == mkv_d->last_pts) &&
|
||||||
!mkv_d->a_skip_to_keyframe)
|
!mkv_d->a_skip_to_keyframe)
|
||||||
dp->pts = 0;
|
dp->pts = 0;
|
||||||
|
@ -2370,6 +2636,7 @@ extern "C" int demux_mkv_fill_buffer(demuxer_t *d) {
|
||||||
demux_packet_t *dp;
|
demux_packet_t *dp;
|
||||||
demux_stream_t *ds;
|
demux_stream_t *ds;
|
||||||
mkv_demuxer_t *mkv_d;
|
mkv_demuxer_t *mkv_d;
|
||||||
|
mkv_track_t *t;
|
||||||
int upper_lvl_el, exit_loop, found_data, i, linei, sl;
|
int upper_lvl_el, exit_loop, found_data, i, linei, sl;
|
||||||
char *texttmp;
|
char *texttmp;
|
||||||
// Elements for different levels
|
// Elements for different levels
|
||||||
|
@ -2490,14 +2757,18 @@ extern "C" int demux_mkv_fill_buffer(demuxer_t *d) {
|
||||||
|
|
||||||
ds = NULL;
|
ds = NULL;
|
||||||
if ((mkv_d->video != NULL) &&
|
if ((mkv_d->video != NULL) &&
|
||||||
(mkv_d->video->tnum == kblock->TrackNum()))
|
(mkv_d->video->tnum == kblock->TrackNum())) {
|
||||||
ds = d->video;
|
ds = d->video;
|
||||||
else if ((mkv_d->audio != NULL) &&
|
t = mkv_d->video;
|
||||||
(mkv_d->audio->tnum == kblock->TrackNum()))
|
} else if ((mkv_d->audio != NULL) &&
|
||||||
|
(mkv_d->audio->tnum == kblock->TrackNum())) {
|
||||||
ds = d->audio;
|
ds = d->audio;
|
||||||
else if ((mkv_d->subs_track != NULL) &&
|
t = mkv_d->audio;
|
||||||
(mkv_d->subs_track->tnum == kblock->TrackNum()))
|
} else if ((mkv_d->subs_track != NULL) &&
|
||||||
|
(mkv_d->subs_track->tnum == kblock->TrackNum())) {
|
||||||
ds = d->sub;
|
ds = d->sub;
|
||||||
|
t = mkv_d->subs_track;
|
||||||
|
}
|
||||||
|
|
||||||
use_this_block = true;
|
use_this_block = true;
|
||||||
|
|
||||||
|
@ -2564,28 +2835,37 @@ extern "C" int demux_mkv_fill_buffer(demuxer_t *d) {
|
||||||
mkv_d->last_filepos = d->filepos;
|
mkv_d->last_filepos = d->filepos;
|
||||||
|
|
||||||
for (i = 0; i < (int)kblock->NumberFrames(); i++) {
|
for (i = 0; i < (int)kblock->NumberFrames(); i++) {
|
||||||
|
unsigned char *re_buffer;
|
||||||
|
uint32_t re_size;
|
||||||
|
bool re_modified;
|
||||||
DataBuffer &data = kblock->GetBuffer(i);
|
DataBuffer &data = kblock->GetBuffer(i);
|
||||||
|
|
||||||
|
re_buffer = data.Buffer();
|
||||||
|
re_size = data.Size();
|
||||||
|
re_modified = reverse_encodings(t, re_buffer, re_size, 1);
|
||||||
|
|
||||||
if ((ds == d->video) && mkv_d->video->realmedia)
|
if ((ds == d->video) && mkv_d->video->realmedia)
|
||||||
handle_realvideo(d, data, block_bref == 0,
|
handle_realvideo(d, re_buffer, re_size, block_bref == 0,
|
||||||
found_data);
|
found_data);
|
||||||
|
|
||||||
else if ((ds == d->audio) && mkv_d->audio->realmedia)
|
else if ((ds == d->audio) && mkv_d->audio->realmedia)
|
||||||
handle_realaudio(d, data, block_bref == 0,
|
handle_realaudio(d, re_buffer, re_size, block_bref == 0,
|
||||||
found_data);
|
found_data);
|
||||||
|
|
||||||
else if ((ds == d->sub) &&
|
else if ((ds == d->sub) &&
|
||||||
(mkv_d->subtitle_type == MKV_SUBTYPE_VOBSUB))
|
(mkv_d->subtitle_type == MKV_SUBTYPE_VOBSUB))
|
||||||
mpeg_run(d, (unsigned char *)data.Buffer(), data.Size());
|
mpeg_run(d, re_buffer, re_size);
|
||||||
|
|
||||||
else {
|
else {
|
||||||
dp = new_demux_packet(data.Size());
|
dp = new_demux_packet(re_size);
|
||||||
memcpy(dp->buffer, data.Buffer(), data.Size());
|
memcpy(dp->buffer, re_buffer, re_size);
|
||||||
dp->flags = block_bref == 0 ? 1 : 0;
|
dp->flags = block_bref == 0 ? 1 : 0;
|
||||||
dp->pts = mkv_d->last_pts;
|
dp->pts = mkv_d->last_pts;
|
||||||
ds_add_packet(ds, dp);
|
ds_add_packet(ds, dp);
|
||||||
found_data++;
|
found_data++;
|
||||||
}
|
}
|
||||||
|
if (re_modified)
|
||||||
|
safefree(re_buffer);
|
||||||
}
|
}
|
||||||
if (ds == d->video) {
|
if (ds == d->video) {
|
||||||
mkv_d->v_skip_to_keyframe = false;
|
mkv_d->v_skip_to_keyframe = false;
|
||||||
|
|
Loading…
Reference in New Issue