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:
mosu 2003-10-22 17:59:28 +00:00
parent 2d0a6214d3
commit 7f54293847
1 changed files with 360 additions and 80 deletions

View File

@ -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;