1
0
mirror of https://github.com/FFmpeg/FFmpeg.git synced 2024-12-23 12:43:46 +02:00

matroskadec: K&R formatting cosmetics

Also sort #includes into canonical order.

Signed-off-by: Diego Biurrun <diego@biurrun.de>
This commit is contained in:
Keiji Costantini 2014-03-01 17:28:15 +01:00 committed by Diego Biurrun
parent 77eed91fab
commit 84cfce9f99

View File

@ -28,28 +28,33 @@
* @see specs available on the Matroska project page: http://www.matroska.org/ * @see specs available on the Matroska project page: http://www.matroska.org/
*/ */
#include "config.h"
#include <stdio.h> #include <stdio.h>
#include "avformat.h"
#include "internal.h"
#include "avio_internal.h"
/* For ff_codec_get_id(). */
#include "riff.h"
#include "isom.h"
#include "rmsipr.h"
#include "matroska.h"
#include "libavcodec/bytestream.h"
#include "libavcodec/mpeg4audio.h"
#include "libavutil/intfloat.h"
#include "libavutil/intreadwrite.h"
#include "libavutil/avstring.h"
#include "libavutil/lzo.h"
#include "libavutil/dict.h"
#if CONFIG_ZLIB
#include <zlib.h>
#endif
#if CONFIG_BZLIB #if CONFIG_BZLIB
#include <bzlib.h> #include <bzlib.h>
#endif #endif
#if CONFIG_ZLIB
#include <zlib.h>
#endif
#include "libavutil/avstring.h"
#include "libavutil/dict.h"
#include "libavutil/intfloat.h"
#include "libavutil/intreadwrite.h"
#include "libavutil/lzo.h"
#include "libavcodec/bytestream.h"
#include "libavcodec/mpeg4audio.h"
#include "avformat.h"
#include "avio_internal.h"
#include "internal.h"
#include "isom.h"
#include "matroska.h"
/* For ff_codec_get_id(). */
#include "riff.h"
#include "rmsipr.h"
typedef enum { typedef enum {
EBML_NONE, EBML_NONE,
@ -581,6 +586,7 @@ static int matroska_resync(MatroskaDemuxContext *matroska, int64_t last_pos)
} }
id = (id << 8) | avio_r8(pb); id = (id << 8) | avio_r8(pb);
} }
eof: eof:
matroska->done = 1; matroska->done = 1;
return AVERROR_EOF; return AVERROR_EOF;
@ -692,13 +698,13 @@ static int ebml_read_uint(AVIOContext *pb, int size, uint64_t *num)
*/ */
static int ebml_read_float(AVIOContext *pb, int size, double *num) static int ebml_read_float(AVIOContext *pb, int size, double *num)
{ {
if (size == 0) { if (size == 0)
*num = 0; *num = 0;
} else if (size == 4) { else if (size == 4)
*num = av_int2float(avio_rb32(pb)); *num = av_int2float(avio_rb32(pb));
} else if (size == 8){ else if (size == 8)
*num = av_int2double(avio_rb64(pb)); *num = av_int2double(avio_rb64(pb));
} else else
return AVERROR_INVALIDDATA; return AVERROR_INVALIDDATA;
return 0; return 0;
@ -914,19 +920,31 @@ static int ebml_parse_elem(MatroskaDemuxContext *matroska,
} }
switch (syntax->type) { switch (syntax->type) {
case EBML_UINT: res = ebml_read_uint (pb, length, data); break; case EBML_UINT:
case EBML_FLOAT: res = ebml_read_float (pb, length, data); break; res = ebml_read_uint(pb, length, data);
break;
case EBML_FLOAT:
res = ebml_read_float(pb, length, data);
break;
case EBML_STR: case EBML_STR:
case EBML_UTF8: res = ebml_read_ascii (pb, length, data); break; case EBML_UTF8:
case EBML_BIN: res = ebml_read_binary(pb, length, data); break; res = ebml_read_ascii(pb, length, data);
case EBML_NEST: if ((res=ebml_read_master(matroska, length)) < 0) break;
case EBML_BIN:
res = ebml_read_binary(pb, length, data);
break;
case EBML_NEST:
if ((res = ebml_read_master(matroska, length)) < 0)
return res; return res;
if (id == MATROSKA_ID_SEGMENT) if (id == MATROSKA_ID_SEGMENT)
matroska->segment_start = avio_tell(matroska->ctx->pb); matroska->segment_start = avio_tell(matroska->ctx->pb);
return ebml_parse_nest(matroska, syntax->def.n, data); return ebml_parse_nest(matroska, syntax->def.n, data);
case EBML_PASS: return ebml_parse_id(matroska, syntax->def.n, id, data); case EBML_PASS:
case EBML_STOP: return 1; return ebml_parse_id(matroska, syntax->def.n, id, data);
default: return avio_skip(pb,length)<0 ? AVERROR(EIO) : 0; case EBML_STOP:
return 1;
default:
return avio_skip(pb, length) < 0 ? AVERROR(EIO) : 0;
} }
if (res == AVERROR_INVALIDDATA) if (res == AVERROR_INVALIDDATA)
av_log(matroska->ctx, AV_LOG_ERROR, "Invalid element\n"); av_log(matroska->ctx, AV_LOG_ERROR, "Invalid element\n");
@ -942,23 +960,28 @@ static void ebml_free(EbmlSyntax *syntax, void *data)
void *data_off = (char *) data + syntax[i].data_offset; void *data_off = (char *) data + syntax[i].data_offset;
switch (syntax[i].type) { switch (syntax[i].type) {
case EBML_STR: case EBML_STR:
case EBML_UTF8: av_freep(data_off); break; case EBML_UTF8:
case EBML_BIN: av_freep(&((EbmlBin *)data_off)->data); break; av_freep(data_off);
break;
case EBML_BIN:
av_freep(&((EbmlBin *) data_off)->data);
break;
case EBML_NEST: case EBML_NEST:
if (syntax[i].list_elem_size) { if (syntax[i].list_elem_size) {
EbmlList *list = data_off; EbmlList *list = data_off;
char *ptr = list->elem; char *ptr = list->elem;
for (j=0; j<list->nb_elem; j++, ptr+=syntax[i].list_elem_size) for (j = 0; j < list->nb_elem;
j++, ptr += syntax[i].list_elem_size)
ebml_free(syntax[i].def.n, ptr); ebml_free(syntax[i].def.n, ptr);
av_free(list->elem); av_free(list->elem);
} else } else
ebml_free(syntax[i].def.n, data_off); ebml_free(syntax[i].def.n, data_off);
default: break; default:
break;
} }
} }
} }
/* /*
* Autodetecting... * Autodetecting...
*/ */
@ -1034,7 +1057,8 @@ static int matroska_decode_buffer(uint8_t** buf, int* buf_size,
return AVERROR_INVALIDDATA; return AVERROR_INVALIDDATA;
switch (encodings[0].compression.algo) { switch (encodings[0].compression.algo) {
case MATROSKA_TRACK_ENCODING_COMP_HEADERSTRIP: { case MATROSKA_TRACK_ENCODING_COMP_HEADERSTRIP:
{
int header_size = encodings[0].compression.settings.size; int header_size = encodings[0].compression.settings.size;
uint8_t *header = encodings[0].compression.settings.data; uint8_t *header = encodings[0].compression.settings.data;
@ -1070,7 +1094,8 @@ static int matroska_decode_buffer(uint8_t** buf, int* buf_size,
break; break;
#endif #endif
#if CONFIG_ZLIB #if CONFIG_ZLIB
case MATROSKA_TRACK_ENCODING_COMP_ZLIB: { case MATROSKA_TRACK_ENCODING_COMP_ZLIB:
{
z_stream zstream = { 0 }; z_stream zstream = { 0 };
if (inflateInit(&zstream) != Z_OK) if (inflateInit(&zstream) != Z_OK)
return -1; return -1;
@ -1101,7 +1126,8 @@ static int matroska_decode_buffer(uint8_t** buf, int* buf_size,
} }
#endif #endif
#if CONFIG_BZLIB #if CONFIG_BZLIB
case MATROSKA_TRACK_ENCODING_COMP_BZLIB: { case MATROSKA_TRACK_ENCODING_COMP_BZLIB:
{
bz_stream bzstream = { 0 }; bz_stream bzstream = { 0 };
if (BZ2_bzDecompressInit(&bzstream, 0, 0) != BZ_OK) if (BZ2_bzDecompressInit(&bzstream, 0, 0) != BZ_OK)
return -1; return -1;
@ -1138,6 +1164,7 @@ static int matroska_decode_buffer(uint8_t** buf, int* buf_size,
*buf = pkt_data; *buf = pkt_data;
*buf_size = pkt_size; *buf_size = pkt_size;
return 0; return 0;
failed: failed:
av_free(pkt_data); av_free(pkt_data);
return result; return result;
@ -1148,26 +1175,36 @@ static void matroska_fix_ass_packet(MatroskaDemuxContext *matroska,
{ {
AVBufferRef *line; AVBufferRef *line;
char *layer, *ptr = pkt->data, *end = ptr + pkt->size; char *layer, *ptr = pkt->data, *end = ptr + pkt->size;
for (; *ptr!=',' && ptr<end-1; ptr++);
for (; *ptr != ',' && ptr < end - 1; ptr++)
;
if (*ptr == ',') if (*ptr == ',')
layer = ++ptr; layer = ++ptr;
for (; *ptr!=',' && ptr<end-1; ptr++); for (; *ptr != ',' && ptr < end - 1; ptr++)
;
if (*ptr == ',') { if (*ptr == ',') {
int64_t end_pts = pkt->pts + display_duration; int64_t end_pts = pkt->pts + display_duration;
int sc = matroska->time_scale * pkt->pts / 10000000; int sc = matroska->time_scale * pkt->pts / 10000000;
int ec = matroska->time_scale * end_pts / 10000000; int ec = matroska->time_scale * end_pts / 10000000;
int sh, sm, ss, eh, em, es, len; int sh, sm, ss, eh, em, es, len;
sh = sc/360000; sc -= 360000*sh; sh = sc / 360000;
sm = sc/ 6000; sc -= 6000*sm; sc -= 360000 * sh;
ss = sc/ 100; sc -= 100*ss; sm = sc / 6000;
eh = ec/360000; ec -= 360000*eh; sc -= 6000 * sm;
em = ec/ 6000; ec -= 6000*em; ss = sc / 100;
es = ec/ 100; ec -= 100*es; sc -= 100 * ss;
eh = ec / 360000;
ec -= 360000 * eh;
em = ec / 6000;
ec -= 6000 * em;
es = ec / 100;
ec -= 100 * es;
*ptr++ = '\0'; *ptr++ = '\0';
len = 50 + end - ptr + FF_INPUT_BUFFER_PADDING_SIZE; len = 50 + end - ptr + FF_INPUT_BUFFER_PADDING_SIZE;
if (!(line = av_buffer_alloc(len))) if (!(line = av_buffer_alloc(len)))
return; return;
snprintf(line->data, len,"Dialogue: %s,%d:%02d:%02d.%02d,%d:%02d:%02d.%02d,%s\r\n", snprintf(line->data, len,
"Dialogue: %s,%d:%02d:%02d.%02d,%d:%02d:%02d.%02d,%s\r\n",
layer, sh, sm, ss, sc, eh, em, es, ec, ptr); layer, sh, sm, ss, sc, eh, em, es, ec, ptr);
av_buffer_unref(&pkt->buf); av_buffer_unref(&pkt->buf);
pkt->buf = line; pkt->buf = line;
@ -1198,15 +1235,17 @@ static void matroska_convert_tag(AVFormatContext *s, EbmlList *list,
int i; int i;
for (i = 0; i < list->nb_elem; i++) { for (i = 0; i < list->nb_elem; i++) {
const char *lang = tags[i].lang && strcmp(tags[i].lang, "und") ? const char *lang = tags[i].lang &&
tags[i].lang : NULL; strcmp(tags[i].lang, "und") ? tags[i].lang : NULL;
if (!tags[i].name) { if (!tags[i].name) {
av_log(s, AV_LOG_WARNING, "Skipping invalid tag with no TagName.\n"); av_log(s, AV_LOG_WARNING, "Skipping invalid tag with no TagName.\n");
continue; continue;
} }
if (prefix) snprintf(key, sizeof(key), "%s/%s", prefix, tags[i].name); if (prefix)
else av_strlcpy(key, tags[i].name, sizeof(key)); snprintf(key, sizeof(key), "%s/%s", prefix, tags[i].name);
else
av_strlcpy(key, tags[i].name, sizeof(key));
if (tags[i].def || !lang) { if (tags[i].def || !lang) {
av_dict_set(metadata, key, tags[i].string, 0); av_dict_set(metadata, key, tags[i].string, 0);
if (tags[i].sub.nb_elem) if (tags[i].sub.nb_elem)
@ -1233,15 +1272,15 @@ static void matroska_convert_tags(AVFormatContext *s)
if (tags[i].target.attachuid) { if (tags[i].target.attachuid) {
MatroskaAttachement *attachment = matroska->attachments.elem; MatroskaAttachement *attachment = matroska->attachments.elem;
for (j = 0; j < matroska->attachments.nb_elem; j++) for (j = 0; j < matroska->attachments.nb_elem; j++)
if (attachment[j].uid == tags[i].target.attachuid if (attachment[j].uid == tags[i].target.attachuid &&
&& attachment[j].stream) attachment[j].stream)
matroska_convert_tag(s, &tags[i].tag, matroska_convert_tag(s, &tags[i].tag,
&attachment[j].stream->metadata, NULL); &attachment[j].stream->metadata, NULL);
} else if (tags[i].target.chapteruid) { } else if (tags[i].target.chapteruid) {
MatroskaChapter *chapter = matroska->chapters.elem; MatroskaChapter *chapter = matroska->chapters.elem;
for (j = 0; j < matroska->chapters.nb_elem; j++) for (j = 0; j < matroska->chapters.nb_elem; j++)
if (chapter[j].uid == tags[i].target.chapteruid if (chapter[j].uid == tags[i].target.chapteruid &&
&& chapter[j].chapter) chapter[j].chapter)
matroska_convert_tag(s, &tags[i].tag, matroska_convert_tag(s, &tags[i].tag,
&chapter[j].chapter->metadata, NULL); &chapter[j].chapter->metadata, NULL);
} else if (tags[i].target.trackuid) { } else if (tags[i].target.trackuid) {
@ -1257,20 +1296,21 @@ static void matroska_convert_tags(AVFormatContext *s)
} }
} }
static int matroska_parse_seekhead_entry(MatroskaDemuxContext *matroska, int idx) static int matroska_parse_seekhead_entry(MatroskaDemuxContext *matroska,
int idx)
{ {
EbmlList *seekhead_list = &matroska->seekhead; EbmlList *seekhead_list = &matroska->seekhead;
MatroskaSeekhead *seekhead = seekhead_list->elem;
uint32_t level_up = matroska->level_up; uint32_t level_up = matroska->level_up;
int64_t before_pos = avio_tell(matroska->ctx->pb);
uint32_t saved_id = matroska->current_id; uint32_t saved_id = matroska->current_id;
MatroskaSeekhead *seekhead = seekhead_list->elem;
int64_t before_pos = avio_tell(matroska->ctx->pb);
MatroskaLevel level; MatroskaLevel level;
int64_t offset; int64_t offset;
int ret = 0; int ret = 0;
if (idx >= seekhead_list->nb_elem if (idx >= seekhead_list->nb_elem ||
|| seekhead[idx].id == MATROSKA_ID_SEEKHEAD seekhead[idx].id == MATROSKA_ID_SEEKHEAD ||
|| seekhead[idx].id == MATROSKA_ID_CLUSTER) seekhead[idx].id == MATROSKA_ID_CLUSTER)
return 0; return 0;
/* seek */ /* seek */
@ -1335,7 +1375,8 @@ static void matroska_execute_seekhead(MatroskaDemuxContext *matroska)
} }
} }
static void matroska_parse_cues(MatroskaDemuxContext *matroska) { static void matroska_parse_cues(MatroskaDemuxContext *matroska)
{
EbmlList *seekhead_list = &matroska->seekhead; EbmlList *seekhead_list = &matroska->seekhead;
MatroskaSeekhead *seekhead = seekhead_list->elem; MatroskaSeekhead *seekhead = seekhead_list->elem;
EbmlList *index_list; EbmlList *index_list;
@ -1352,8 +1393,8 @@ static void matroska_parse_cues(MatroskaDemuxContext *matroska) {
index_list = &matroska->index; index_list = &matroska->index;
index = index_list->elem; index = index_list->elem;
if (index_list->nb_elem if (index_list->nb_elem &&
&& index[0].time > 1E14/matroska->time_scale) { index[0].time > 1E14 / matroska->time_scale) {
av_log(matroska->ctx, AV_LOG_WARNING, "Working around broken index.\n"); av_log(matroska->ctx, AV_LOG_WARNING, "Working around broken index.\n");
index_scale = matroska->time_scale; index_scale = matroska->time_scale;
} }
@ -1361,7 +1402,8 @@ static void matroska_parse_cues(MatroskaDemuxContext *matroska) {
EbmlList *pos_list = &index[i].pos; EbmlList *pos_list = &index[i].pos;
MatroskaIndexPos *pos = pos_list->elem; MatroskaIndexPos *pos = pos_list->elem;
for (j = 0; j < pos_list->nb_elem; j++) { for (j = 0; j < pos_list->nb_elem; j++) {
MatroskaTrack *track = matroska_find_track_by_num(matroska, pos[j].track); MatroskaTrack *track = matroska_find_track_by_num(matroska,
pos[j].track);
if (track && track->stream) if (track && track->stream)
av_add_index_entry(track->stream, av_add_index_entry(track->stream,
pos[j].pos + matroska->segment_start, pos[j].pos + matroska->segment_start,
@ -1396,8 +1438,8 @@ static int matroska_read_header(AVFormatContext *s)
{ {
MatroskaDemuxContext *matroska = s->priv_data; MatroskaDemuxContext *matroska = s->priv_data;
EbmlList *attachements_list = &matroska->attachments; EbmlList *attachements_list = &matroska->attachments;
MatroskaAttachement *attachements;
EbmlList *chapters_list = &matroska->chapters; EbmlList *chapters_list = &matroska->chapters;
MatroskaAttachement *attachements;
MatroskaChapter *chapters; MatroskaChapter *chapters;
MatroskaTrack *tracks; MatroskaTrack *tracks;
uint64_t max_start = 0; uint64_t max_start = 0;
@ -1409,9 +1451,11 @@ static int matroska_read_header(AVFormatContext *s)
matroska->ctx = s; matroska->ctx = s;
/* First read the EBML header. */ /* First read the EBML header. */
if (ebml_parse(matroska, ebml_syntax, &ebml) if (ebml_parse(matroska, ebml_syntax, &ebml) ||
|| ebml.version > EBML_VERSION || ebml.max_size > sizeof(uint64_t) ebml.version > EBML_VERSION ||
|| ebml.id_length > sizeof(uint32_t) || ebml.doctype_version > 2) { ebml.max_size > sizeof(uint64_t) ||
ebml.id_length > sizeof(uint32_t) ||
ebml.doctype_version > 2) {
av_log(matroska->ctx, AV_LOG_ERROR, av_log(matroska->ctx, AV_LOG_ERROR,
"EBML header using unsupported features\n" "EBML header using unsupported features\n"
"(EBML version %"PRIu64", doctype %s, doc version %"PRIu64")\n", "(EBML version %"PRIu64", doctype %s, doc version %"PRIu64")\n",
@ -1447,8 +1491,8 @@ static int matroska_read_header(AVFormatContext *s)
if (!matroska->time_scale) if (!matroska->time_scale)
matroska->time_scale = 1000000; matroska->time_scale = 1000000;
if (matroska->duration) if (matroska->duration)
matroska->ctx->duration = matroska->duration * matroska->time_scale matroska->ctx->duration = matroska->duration * matroska->time_scale *
* 1000 / AV_TIME_BASE; 1000 / AV_TIME_BASE;
av_dict_set(&s->metadata, "title", matroska->title, 0); av_dict_set(&s->metadata, "title", matroska->title, 0);
tracks = matroska->tracks.elem; tracks = matroska->tracks.elem;
@ -1533,42 +1577,58 @@ static int matroska_read_header(AVFormatContext *s)
if (st == NULL) if (st == NULL)
return AVERROR(ENOMEM); return AVERROR(ENOMEM);
if (!strcmp(track->codec_id, "V_MS/VFW/FOURCC") if (!strcmp(track->codec_id, "V_MS/VFW/FOURCC") &&
&& track->codec_priv.size >= 40 track->codec_priv.size >= 40 &&
&& track->codec_priv.data != NULL) { track->codec_priv.data != NULL) {
track->ms_compat = 1; track->ms_compat = 1;
track->video.fourcc = AV_RL32(track->codec_priv.data + 16); track->video.fourcc = AV_RL32(track->codec_priv.data + 16);
codec_id = ff_codec_get_id(ff_codec_bmp_tags, track->video.fourcc); codec_id = ff_codec_get_id(ff_codec_bmp_tags,
track->video.fourcc);
extradata_offset = 40; extradata_offset = 40;
} else if (!strcmp(track->codec_id, "A_MS/ACM") } else if (!strcmp(track->codec_id, "A_MS/ACM") &&
&& track->codec_priv.size >= 14 track->codec_priv.size >= 14 &&
&& track->codec_priv.data != NULL) { track->codec_priv.data != NULL) {
int ret; int ret;
ffio_init_context(&b, track->codec_priv.data, track->codec_priv.size, ffio_init_context(&b, track->codec_priv.data,
track->codec_priv.size,
0, NULL, NULL, NULL, NULL); 0, NULL, NULL, NULL, NULL);
ret = ff_get_wav_header(&b, st->codec, track->codec_priv.size); ret = ff_get_wav_header(&b, st->codec, track->codec_priv.size);
if (ret < 0) if (ret < 0)
return ret; return ret;
codec_id = st->codec->codec_id; codec_id = st->codec->codec_id;
extradata_offset = FFMIN(track->codec_priv.size, 18); extradata_offset = FFMIN(track->codec_priv.size, 18);
} else if (!strcmp(track->codec_id, "V_QUICKTIME") } else if (!strcmp(track->codec_id, "V_QUICKTIME") &&
&& (track->codec_priv.size >= 86) (track->codec_priv.size >= 86) &&
&& (track->codec_priv.data != NULL)) { (track->codec_priv.data != NULL)) {
track->video.fourcc = AV_RL32(track->codec_priv.data); track->video.fourcc = AV_RL32(track->codec_priv.data);
codec_id=ff_codec_get_id(ff_codec_movvideo_tags, track->video.fourcc); codec_id = ff_codec_get_id(ff_codec_movvideo_tags,
track->video.fourcc);
} else if (codec_id == AV_CODEC_ID_PCM_S16BE) { } else if (codec_id == AV_CODEC_ID_PCM_S16BE) {
switch (track->audio.bitdepth) { switch (track->audio.bitdepth) {
case 8: codec_id = AV_CODEC_ID_PCM_U8; break; case 8:
case 24: codec_id = AV_CODEC_ID_PCM_S24BE; break; codec_id = AV_CODEC_ID_PCM_U8;
case 32: codec_id = AV_CODEC_ID_PCM_S32BE; break; break;
case 24:
codec_id = AV_CODEC_ID_PCM_S24BE;
break;
case 32:
codec_id = AV_CODEC_ID_PCM_S32BE;
break;
} }
} else if (codec_id == AV_CODEC_ID_PCM_S16LE) { } else if (codec_id == AV_CODEC_ID_PCM_S16LE) {
switch (track->audio.bitdepth) { switch (track->audio.bitdepth) {
case 8: codec_id = AV_CODEC_ID_PCM_U8; break; case 8:
case 24: codec_id = AV_CODEC_ID_PCM_S24LE; break; codec_id = AV_CODEC_ID_PCM_U8;
case 32: codec_id = AV_CODEC_ID_PCM_S32LE; break; break;
case 24:
codec_id = AV_CODEC_ID_PCM_S24LE;
break;
case 32:
codec_id = AV_CODEC_ID_PCM_S32LE;
break;
} }
} else if (codec_id==AV_CODEC_ID_PCM_F32LE && track->audio.bitdepth==64) { } else if (codec_id == AV_CODEC_ID_PCM_F32LE &&
track->audio.bitdepth == 64) {
codec_id = AV_CODEC_ID_PCM_F64LE; codec_id = AV_CODEC_ID_PCM_F64LE;
} else if (codec_id == AV_CODEC_ID_AAC && !track->codec_priv.size) { } else if (codec_id == AV_CODEC_ID_AAC && !track->codec_priv.size) {
int profile = matroska_aac_profile(track->codec_id); int profile = matroska_aac_profile(track->codec_id);
@ -1588,10 +1648,11 @@ static int matroska_read_header(AVFormatContext *s)
extradata_size = 2; extradata_size = 2;
} else if (codec_id == AV_CODEC_ID_ALAC && track->codec_priv.size) { } else if (codec_id == AV_CODEC_ID_ALAC && track->codec_priv.size) {
/* Only ALAC's magic cookie is stored in Matroska's track headers. /* Only ALAC's magic cookie is stored in Matroska's track headers.
Create the "atom size", "tag", and "tag version" fields the * Create the "atom size", "tag", and "tag version" fields the
decoder expects manually. */ * decoder expects manually. */
extradata_size = 12 + track->codec_priv.size; extradata_size = 12 + track->codec_priv.size;
extradata = av_mallocz(extradata_size + FF_INPUT_BUFFER_PADDING_SIZE); extradata = av_mallocz(extradata_size +
FF_INPUT_BUFFER_PADDING_SIZE);
if (extradata == NULL) if (extradata == NULL)
return AVERROR(ENOMEM); return AVERROR(ENOMEM);
AV_WB32(extradata, extradata_size); AV_WB32(extradata, extradata_size);
@ -1611,17 +1672,23 @@ static int matroska_read_header(AVFormatContext *s)
avio_wl16(&b, track->audio.channels); avio_wl16(&b, track->audio.channels);
avio_wl16(&b, track->audio.bitdepth); avio_wl16(&b, track->audio.bitdepth);
avio_wl32(&b, track->audio.out_samplerate); avio_wl32(&b, track->audio.out_samplerate);
avio_wl32(&b, matroska->ctx->duration * track->audio.out_samplerate); avio_wl32(&b, matroska->ctx->duration *
} else if (codec_id == AV_CODEC_ID_RV10 || codec_id == AV_CODEC_ID_RV20 || track->audio.out_samplerate);
codec_id == AV_CODEC_ID_RV30 || codec_id == AV_CODEC_ID_RV40) { } else if (codec_id == AV_CODEC_ID_RV10 ||
codec_id == AV_CODEC_ID_RV20 ||
codec_id == AV_CODEC_ID_RV30 ||
codec_id == AV_CODEC_ID_RV40) {
extradata_offset = 26; extradata_offset = 26;
} else if (codec_id == AV_CODEC_ID_RA_144) { } else if (codec_id == AV_CODEC_ID_RA_144) {
track->audio.out_samplerate = 8000; track->audio.out_samplerate = 8000;
track->audio.channels = 1; track->audio.channels = 1;
} else if (codec_id == AV_CODEC_ID_RA_288 || codec_id == AV_CODEC_ID_COOK || } else if (codec_id == AV_CODEC_ID_RA_288 ||
codec_id == AV_CODEC_ID_ATRAC3 || codec_id == AV_CODEC_ID_SIPR) { codec_id == AV_CODEC_ID_COOK ||
codec_id == AV_CODEC_ID_ATRAC3 ||
codec_id == AV_CODEC_ID_SIPR) {
int flavor; int flavor;
ffio_init_context(&b, track->codec_priv.data,track->codec_priv.size, ffio_init_context(&b, track->codec_priv.data,
track->codec_priv.size,
0, NULL, NULL, NULL, NULL); 0, NULL, NULL, NULL, NULL);
avio_skip(&b, 22); avio_skip(&b, 22);
flavor = avio_rb16(&b); flavor = avio_rb16(&b);
@ -1630,11 +1697,14 @@ static int matroska_read_header(AVFormatContext *s)
track->audio.sub_packet_h = avio_rb16(&b); track->audio.sub_packet_h = avio_rb16(&b);
track->audio.frame_size = avio_rb16(&b); track->audio.frame_size = avio_rb16(&b);
track->audio.sub_packet_size = avio_rb16(&b); track->audio.sub_packet_size = avio_rb16(&b);
if (flavor <= 0 || track->audio.coded_framesize <= 0 || if (flavor <= 0 ||
track->audio.sub_packet_h <= 0 || track->audio.frame_size <= 0 || track->audio.coded_framesize <= 0 ||
track->audio.sub_packet_h <= 0 ||
track->audio.frame_size <= 0 ||
track->audio.sub_packet_size <= 0) track->audio.sub_packet_size <= 0)
return AVERROR_INVALIDDATA; return AVERROR_INVALIDDATA;
track->audio.buf = av_malloc(track->audio.frame_size * track->audio.sub_packet_h); track->audio.buf = av_malloc(track->audio.frame_size *
track->audio.sub_packet_h);
if (codec_id == AV_CODEC_ID_RA_288) { if (codec_id == AV_CODEC_ID_RA_288) {
st->codec->block_align = track->audio.coded_framesize; st->codec->block_align = track->audio.coded_framesize;
track->codec_priv.size = 0; track->codec_priv.size = 0;
@ -1656,7 +1726,8 @@ static int matroska_read_header(AVFormatContext *s)
if (track->time_scale < 0.01) if (track->time_scale < 0.01)
track->time_scale = 1.0; track->time_scale = 1.0;
avpriv_set_pts_info(st, 64, matroska->time_scale*track->time_scale, 1000*1000*1000); /* 64 bit pts in ns */ avpriv_set_pts_info(st, 64, matroska->time_scale * track->time_scale,
1000 * 1000 * 1000); /* 64 bit pts in ns */
st->codec->codec_id = codec_id; st->codec->codec_id = codec_id;
st->start_time = 0; st->start_time = 0;
@ -1732,7 +1803,8 @@ static int matroska_read_header(AVFormatContext *s)
if (st->codec->extradata == NULL) if (st->codec->extradata == NULL)
break; break;
st->codec->extradata_size = attachements[j].bin.size; st->codec->extradata_size = attachements[j].bin.size;
memcpy(st->codec->extradata, attachements[j].bin.data, attachements[j].bin.size); memcpy(st->codec->extradata, attachements[j].bin.data,
attachements[j].bin.size);
for (i = 0; ff_mkv_mime_tags[i].id != AV_CODEC_ID_NONE; i++) { for (i = 0; ff_mkv_mime_tags[i].id != AV_CODEC_ID_NONE; i++) {
if (!strncmp(ff_mkv_mime_tags[i].str, attachements[j].mime, if (!strncmp(ff_mkv_mime_tags[i].str, attachements[j].mime,
@ -1747,10 +1819,11 @@ static int matroska_read_header(AVFormatContext *s)
chapters = chapters_list->elem; chapters = chapters_list->elem;
for (i = 0; i < chapters_list->nb_elem; i++) for (i = 0; i < chapters_list->nb_elem; i++)
if (chapters[i].start != AV_NOPTS_VALUE && chapters[i].uid if (chapters[i].start != AV_NOPTS_VALUE && chapters[i].uid &&
&& (max_start==0 || chapters[i].start > max_start)) { (max_start == 0 || chapters[i].start > max_start)) {
chapters[i].chapter = chapters[i].chapter =
avpriv_new_chapter(s, chapters[i].uid, (AVRational){1, 1000000000}, avpriv_new_chapter(s, chapters[i].uid,
(AVRational) { 1, 1000000000 },
chapters[i].start, chapters[i].end, chapters[i].start, chapters[i].end,
chapters[i].title); chapters[i].title);
av_dict_set(&chapters[i].chapter->metadata, av_dict_set(&chapters[i].chapter->metadata,
@ -1778,7 +1851,8 @@ static int matroska_deliver_packet(MatroskaDemuxContext *matroska,
memmove(&matroska->packets[0], &matroska->packets[1], memmove(&matroska->packets[0], &matroska->packets[1],
(matroska->num_packets - 1) * sizeof(AVPacket *)); (matroska->num_packets - 1) * sizeof(AVPacket *));
newpackets = av_realloc(matroska->packets, newpackets = av_realloc(matroska->packets,
(matroska->num_packets - 1) * sizeof(AVPacket *)); (matroska->num_packets - 1) *
sizeof(AVPacket *));
if (newpackets) if (newpackets)
matroska->packets = newpackets; matroska->packets = newpackets;
} else { } else {
@ -1836,7 +1910,8 @@ static int matroska_parse_laces(MatroskaDemuxContext *matroska, uint8_t **buf,
return AVERROR(ENOMEM); return AVERROR(ENOMEM);
switch (type) { switch (type) {
case 0x1: /* Xiph lacing */ { case 0x1: /* Xiph lacing */
{
uint8_t temp; uint8_t temp;
uint32_t total = 0; uint32_t total = 0;
for (n = 0; res == 0 && n < *laces - 1; n++) { for (n = 0; res == 0 && n < *laces - 1; n++) {
@ -1872,7 +1947,8 @@ static int matroska_parse_laces(MatroskaDemuxContext *matroska, uint8_t **buf,
lace_size[n] = size / *laces; lace_size[n] = size / *laces;
break; break;
case 0x3: /* EBML lacing */ { case 0x3: /* EBML lacing */
{
uint64_t num; uint64_t num;
uint64_t total; uint64_t total;
n = matroska_ebmlnum_uint(matroska, data, size, &num); n = matroska_ebmlnum_uint(matroska, data, size, &num);
@ -1917,11 +1993,9 @@ static int matroska_parse_laces(MatroskaDemuxContext *matroska, uint8_t **buf,
} }
static int matroska_parse_rm_audio(MatroskaDemuxContext *matroska, static int matroska_parse_rm_audio(MatroskaDemuxContext *matroska,
MatroskaTrack *track, MatroskaTrack *track, AVStream *st,
AVStream *st, uint8_t *data, int size, uint64_t timecode,
uint8_t *data, int size, uint64_t duration, int64_t pos)
uint64_t timecode, uint64_t duration,
int64_t pos)
{ {
int a = st->codec->block_align; int a = st->codec->block_align;
int sps = track->audio.sub_packet_size; int sps = track->audio.sub_packet_size;
@ -1957,7 +2031,9 @@ static int matroska_parse_rm_audio(MatroskaDemuxContext *matroska,
return AVERROR_INVALIDDATA; return AVERROR_INVALIDDATA;
} }
for (x = 0; x < w / sps; x++) for (x = 0; x < w / sps; x++)
memcpy(track->audio.buf+sps*(h*x+((h+1)/2)*(y&1)+(y>>1)), data+x*sps, sps); memcpy(track->audio.buf +
sps * (h * x + ((h + 1) / 2) * (y & 1) + (y >> 1)),
data + x * sps, sps);
} }
if (++track->audio.sub_packet_cnt >= h) { if (++track->audio.sub_packet_cnt >= h) {
@ -1971,8 +2047,9 @@ static int matroska_parse_rm_audio(MatroskaDemuxContext *matroska,
while (track->audio.pkt_cnt) { while (track->audio.pkt_cnt) {
AVPacket *pkt = av_mallocz(sizeof(AVPacket)); AVPacket *pkt = av_mallocz(sizeof(AVPacket));
av_new_packet(pkt, a); av_new_packet(pkt, a);
memcpy(pkt->data, track->audio.buf memcpy(pkt->data,
+ a * (h*w / a - track->audio.pkt_cnt--), a); track->audio.buf + a * (h * w / a - track->audio.pkt_cnt--),
a);
pkt->pts = track->audio.buf_timecode; pkt->pts = track->audio.buf_timecode;
track->audio.buf_timecode = AV_NOPTS_VALUE; track->audio.buf_timecode = AV_NOPTS_VALUE;
pkt->pos = pos; pkt->pos = pos;
@ -2065,8 +2142,7 @@ fail:
} }
static int matroska_parse_frame(MatroskaDemuxContext *matroska, static int matroska_parse_frame(MatroskaDemuxContext *matroska,
MatroskaTrack *track, MatroskaTrack *track, AVStream *st,
AVStream *st,
uint8_t *data, int pkt_size, uint8_t *data, int pkt_size,
uint64_t timecode, uint64_t duration, uint64_t timecode, uint64_t duration,
int64_t pos, int is_keyframe) int64_t pos, int is_keyframe)
@ -2086,7 +2162,8 @@ static int matroska_parse_frame(MatroskaDemuxContext *matroska,
uint8_t *wv_data; uint8_t *wv_data;
res = matroska_parse_wavpack(track, pkt_data, &wv_data, &pkt_size); res = matroska_parse_wavpack(track, pkt_data, &wv_data, &pkt_size);
if (res < 0) { if (res < 0) {
av_log(matroska->ctx, AV_LOG_ERROR, "Error parsing a wavpack block.\n"); av_log(matroska->ctx, AV_LOG_ERROR,
"Error parsing a wavpack block.\n");
goto fail; goto fail;
} }
if (pkt_data != data) if (pkt_data != data)
@ -2143,6 +2220,7 @@ static int matroska_parse_frame(MatroskaDemuxContext *matroska,
} }
return 0; return 0;
fail: fail:
if (pkt_data != data) if (pkt_data != data)
av_freep(&pkt_data); av_freep(&pkt_data);
@ -2188,17 +2266,19 @@ static int matroska_parse_block(MatroskaDemuxContext *matroska, uint8_t *data,
if (is_keyframe == -1) if (is_keyframe == -1)
is_keyframe = flags & 0x80 ? AV_PKT_FLAG_KEY : 0; is_keyframe = flags & 0x80 ? AV_PKT_FLAG_KEY : 0;
if (cluster_time != (uint64_t)-1 if (cluster_time != (uint64_t) -1 &&
&& (block_time >= 0 || cluster_time >= -block_time)) { (block_time >= 0 || cluster_time >= -block_time)) {
timecode = cluster_time + block_time; timecode = cluster_time + block_time;
if (track->type == MATROSKA_TRACK_TYPE_SUBTITLE if (track->type == MATROSKA_TRACK_TYPE_SUBTITLE &&
&& timecode < track->end_timecode) timecode < track->end_timecode)
is_keyframe = 0; /* overlapping subtitles are not key frame */ is_keyframe = 0; /* overlapping subtitles are not key frame */
if (is_keyframe) if (is_keyframe)
av_add_index_entry(st, cluster_pos, timecode, 0,0,AVINDEX_KEYFRAME); av_add_index_entry(st, cluster_pos, timecode, 0, 0,
AVINDEX_KEYFRAME);
} }
if (matroska->skip_to_keyframe && track->type != MATROSKA_TRACK_TYPE_SUBTITLE) { if (matroska->skip_to_keyframe &&
track->type != MATROSKA_TRACK_TYPE_SUBTITLE) {
if (!is_keyframe || timecode < matroska->skip_to_timecode) if (!is_keyframe || timecode < matroska->skip_to_timecode)
return res; return res;
matroska->skip_to_keyframe = 0; matroska->skip_to_keyframe = 0;
@ -2231,17 +2311,15 @@ static int matroska_parse_block(MatroskaDemuxContext *matroska, uint8_t *data,
st->codec->codec_id == AV_CODEC_ID_SIPR || st->codec->codec_id == AV_CODEC_ID_SIPR ||
st->codec->codec_id == AV_CODEC_ID_ATRAC3) && st->codec->codec_id == AV_CODEC_ID_ATRAC3) &&
st->codec->block_align && track->audio.sub_packet_size) { st->codec->block_align && track->audio.sub_packet_size) {
res = matroska_parse_rm_audio(matroska, track, st, data, res = matroska_parse_rm_audio(matroska, track, st, data,
lace_size[n], lace_size[n],
timecode, duration, pos); timecode, duration, pos);
if (res) if (res)
goto end; goto end;
} else { } else {
res = matroska_parse_frame(matroska, track, st, data, lace_size[n], res = matroska_parse_frame(matroska, track, st, data, lace_size[n],
timecode, duration, timecode, duration, pos,
pos, !n? is_keyframe : 0); !n ? is_keyframe : 0);
if (res) if (res)
goto end; goto end;
} }
@ -2298,16 +2376,16 @@ static int matroska_parse_cluster_incremental(MatroskaDemuxContext *matroska)
int is_keyframe = blocks[i].non_simple ? !blocks[i].reference : -1; int is_keyframe = blocks[i].non_simple ? !blocks[i].reference : -1;
if (!blocks[i].non_simple) if (!blocks[i].non_simple)
blocks[i].duration = AV_NOPTS_VALUE; blocks[i].duration = AV_NOPTS_VALUE;
res = matroska_parse_block(matroska, res = matroska_parse_block(matroska, blocks[i].bin.data,
blocks[i].bin.data, blocks[i].bin.size, blocks[i].bin.size, blocks[i].bin.pos,
blocks[i].bin.pos,
matroska->current_cluster.timecode, matroska->current_cluster.timecode,
blocks[i].duration, is_keyframe, blocks[i].duration, is_keyframe,
matroska->current_cluster_pos); matroska->current_cluster_pos);
} }
} }
if (res < 0) matroska->done = 1; if (res < 0)
matroska->done = 1;
return res; return res;
} }
@ -2318,6 +2396,7 @@ static int matroska_parse_cluster(MatroskaDemuxContext *matroska)
MatroskaBlock *blocks; MatroskaBlock *blocks;
int i, res; int i, res;
int64_t pos; int64_t pos;
if (!matroska->contains_ssa) if (!matroska->contains_ssa)
return matroska_parse_cluster_incremental(matroska); return matroska_parse_cluster_incremental(matroska);
pos = avio_tell(matroska->ctx->pb); pos = avio_tell(matroska->ctx->pb);
@ -2332,11 +2411,10 @@ static int matroska_parse_cluster(MatroskaDemuxContext *matroska)
int is_keyframe = blocks[i].non_simple ? !blocks[i].reference : -1; int is_keyframe = blocks[i].non_simple ? !blocks[i].reference : -1;
if (!blocks[i].non_simple) if (!blocks[i].non_simple)
blocks[i].duration = AV_NOPTS_VALUE; blocks[i].duration = AV_NOPTS_VALUE;
res=matroska_parse_block(matroska, res = matroska_parse_block(matroska, blocks[i].bin.data,
blocks[i].bin.data, blocks[i].bin.size, blocks[i].bin.size, blocks[i].bin.pos,
blocks[i].bin.pos, cluster.timecode, cluster.timecode, blocks[i].duration,
blocks[i].duration, is_keyframe, is_keyframe, pos);
pos);
} }
ebml_free(matroska_cluster, &cluster); ebml_free(matroska_cluster, &cluster);
return res; return res;
@ -2382,7 +2460,8 @@ static int matroska_read_seek(AVFormatContext *s, int stream_index,
timestamp = FFMAX(timestamp, st->index_entries[0].timestamp); timestamp = FFMAX(timestamp, st->index_entries[0].timestamp);
if ((index = av_index_search_timestamp(st, timestamp, flags)) < 0) { if ((index = av_index_search_timestamp(st, timestamp, flags)) < 0) {
avio_seek(s->pb, st->index_entries[st->nb_index_entries-1].pos, SEEK_SET); avio_seek(s->pb, st->index_entries[st->nb_index_entries - 1].pos,
SEEK_SET);
matroska->current_id = 0; matroska->current_id = 0;
while ((index = av_index_search_timestamp(st, timestamp, flags)) < 0) { while ((index = av_index_search_timestamp(st, timestamp, flags)) < 0) {
matroska_clear_queue(matroska); matroska_clear_queue(matroska);
@ -2401,12 +2480,15 @@ static int matroska_read_seek(AVFormatContext *s, int stream_index,
tracks[i].audio.sub_packet_cnt = 0; tracks[i].audio.sub_packet_cnt = 0;
tracks[i].audio.buf_timecode = AV_NOPTS_VALUE; tracks[i].audio.buf_timecode = AV_NOPTS_VALUE;
tracks[i].end_timecode = 0; tracks[i].end_timecode = 0;
if (tracks[i].type == MATROSKA_TRACK_TYPE_SUBTITLE if (tracks[i].type == MATROSKA_TRACK_TYPE_SUBTITLE &&
&& !tracks[i].stream->discard != AVDISCARD_ALL) { !tracks[i].stream->discard != AVDISCARD_ALL) {
index_sub = av_index_search_timestamp(tracks[i].stream, st->index_entries[index].timestamp, AVSEEK_FLAG_BACKWARD); index_sub = av_index_search_timestamp(
if (index_sub >= 0 tracks[i].stream, st->index_entries[index].timestamp,
&& st->index_entries[index_sub].pos < st->index_entries[index_min].pos AVSEEK_FLAG_BACKWARD);
&& st->index_entries[index].timestamp - st->index_entries[index_sub].timestamp < 30000000000/matroska->time_scale) if (index_sub >= 0 &&
st->index_entries[index_sub].pos < st->index_entries[index_min].pos &&
st->index_entries[index].timestamp -
st->index_entries[index_sub].timestamp < 30000000000 / matroska->time_scale)
index_min = index_sub; index_min = index_sub;
} }
} }