|
|
@@ -325,26 +325,26 @@ static void end_ebml_master(AVIOContext *pb, ebml_master master) |
|
|
avio_seek(pb, pos, SEEK_SET); |
|
|
avio_seek(pb, pos, SEEK_SET); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
static int start_ebml_master_crc32(AVIOContext *pb, AVIOContext **dyn_cp, MatroskaMuxContext *mkv, |
|
|
|
|
|
uint32_t elementid) |
|
|
|
|
|
|
|
|
static int start_ebml_master_crc32(AVIOContext **dyn_cp, MatroskaMuxContext *mkv) |
|
|
{ |
|
|
{ |
|
|
int ret; |
|
|
int ret; |
|
|
|
|
|
|
|
|
if ((ret = avio_open_dyn_buf(dyn_cp)) < 0) |
|
|
if ((ret = avio_open_dyn_buf(dyn_cp)) < 0) |
|
|
return ret; |
|
|
return ret; |
|
|
|
|
|
|
|
|
put_ebml_id(pb, elementid); |
|
|
|
|
|
if (mkv->write_crc) |
|
|
if (mkv->write_crc) |
|
|
put_ebml_void(*dyn_cp, 6); /* Reserve space for CRC32 so position/size calculations using avio_tell() take it into account */ |
|
|
put_ebml_void(*dyn_cp, 6); /* Reserve space for CRC32 so position/size calculations using avio_tell() take it into account */ |
|
|
|
|
|
|
|
|
return 0; |
|
|
return 0; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
static void end_ebml_master_crc32(AVIOContext *pb, AVIOContext **dyn_cp, MatroskaMuxContext *mkv) |
|
|
|
|
|
|
|
|
static void end_ebml_master_crc32(AVIOContext *pb, AVIOContext **dyn_cp, |
|
|
|
|
|
MatroskaMuxContext *mkv, uint32_t id) |
|
|
{ |
|
|
{ |
|
|
uint8_t *buf, crc[4]; |
|
|
uint8_t *buf, crc[4]; |
|
|
int size, skip = 0; |
|
|
int size, skip = 0; |
|
|
|
|
|
|
|
|
|
|
|
put_ebml_id(pb, id); |
|
|
size = avio_close_dyn_buf(*dyn_cp, &buf); |
|
|
size = avio_close_dyn_buf(*dyn_cp, &buf); |
|
|
put_ebml_num(pb, size, 0); |
|
|
put_ebml_num(pb, size, 0); |
|
|
if (mkv->write_crc) { |
|
|
if (mkv->write_crc) { |
|
|
@@ -362,13 +362,14 @@ static void end_ebml_master_crc32(AVIOContext *pb, AVIOContext **dyn_cp, Matrosk |
|
|
* Complete ebml master without destroying the buffer, allowing for later updates |
|
|
* Complete ebml master without destroying the buffer, allowing for later updates |
|
|
*/ |
|
|
*/ |
|
|
static void end_ebml_master_crc32_preliminary(AVIOContext *pb, AVIOContext **dyn_cp, MatroskaMuxContext *mkv, |
|
|
static void end_ebml_master_crc32_preliminary(AVIOContext *pb, AVIOContext **dyn_cp, MatroskaMuxContext *mkv, |
|
|
int64_t *pos) |
|
|
|
|
|
|
|
|
uint32_t id, int64_t *pos) |
|
|
{ |
|
|
{ |
|
|
uint8_t *buf; |
|
|
uint8_t *buf; |
|
|
int size = avio_get_dyn_buf(*dyn_cp, &buf); |
|
|
int size = avio_get_dyn_buf(*dyn_cp, &buf); |
|
|
|
|
|
|
|
|
*pos = avio_tell(pb); |
|
|
*pos = avio_tell(pb); |
|
|
|
|
|
|
|
|
|
|
|
put_ebml_id(pb, id); |
|
|
put_ebml_num(pb, size, 0); |
|
|
put_ebml_num(pb, size, 0); |
|
|
avio_write(pb, buf, size); |
|
|
avio_write(pb, buf, size); |
|
|
} |
|
|
} |
|
|
@@ -448,7 +449,7 @@ static int mkv_write_seekhead(AVIOContext *pb, MatroskaMuxContext *mkv, |
|
|
if ((ret64 = avio_seek(pb, seekhead->filepos, SEEK_SET)) < 0) |
|
|
if ((ret64 = avio_seek(pb, seekhead->filepos, SEEK_SET)) < 0) |
|
|
return error_on_seek_failure ? ret64 : 0; |
|
|
return error_on_seek_failure ? ret64 : 0; |
|
|
|
|
|
|
|
|
ret = start_ebml_master_crc32(pb, &dyn_cp, mkv, MATROSKA_ID_SEEKHEAD); |
|
|
|
|
|
|
|
|
ret = start_ebml_master_crc32(&dyn_cp, mkv); |
|
|
if (ret < 0) |
|
|
if (ret < 0) |
|
|
return ret; |
|
|
return ret; |
|
|
|
|
|
|
|
|
@@ -464,7 +465,7 @@ static int mkv_write_seekhead(AVIOContext *pb, MatroskaMuxContext *mkv, |
|
|
put_ebml_uint(dyn_cp, MATROSKA_ID_SEEKPOSITION, entry->segmentpos); |
|
|
put_ebml_uint(dyn_cp, MATROSKA_ID_SEEKPOSITION, entry->segmentpos); |
|
|
end_ebml_master(dyn_cp, seekentry); |
|
|
end_ebml_master(dyn_cp, seekentry); |
|
|
} |
|
|
} |
|
|
end_ebml_master_crc32(pb, &dyn_cp, mkv); |
|
|
|
|
|
|
|
|
end_ebml_master_crc32(pb, &dyn_cp, mkv, MATROSKA_ID_SEEKHEAD); |
|
|
|
|
|
|
|
|
remaining = seekhead->filepos + seekhead->reserved_size - avio_tell(pb); |
|
|
remaining = seekhead->filepos + seekhead->reserved_size - avio_tell(pb); |
|
|
put_ebml_void(pb, remaining); |
|
|
put_ebml_void(pb, remaining); |
|
|
@@ -507,7 +508,7 @@ static int64_t mkv_write_cues(AVFormatContext *s, mkv_cues *cues, mkv_track *tra |
|
|
int ret; |
|
|
int ret; |
|
|
|
|
|
|
|
|
currentpos = avio_tell(pb); |
|
|
currentpos = avio_tell(pb); |
|
|
ret = start_ebml_master_crc32(pb, &dyn_cp, mkv, MATROSKA_ID_CUES); |
|
|
|
|
|
|
|
|
ret = start_ebml_master_crc32(&dyn_cp, mkv); |
|
|
if (ret < 0) |
|
|
if (ret < 0) |
|
|
return ret; |
|
|
return ret; |
|
|
|
|
|
|
|
|
@@ -550,7 +551,7 @@ static int64_t mkv_write_cues(AVFormatContext *s, mkv_cues *cues, mkv_track *tra |
|
|
ffio_reset_dyn_buf(cuepoint); |
|
|
ffio_reset_dyn_buf(cuepoint); |
|
|
} |
|
|
} |
|
|
ffio_free_dyn_buf(&cuepoint); |
|
|
ffio_free_dyn_buf(&cuepoint); |
|
|
end_ebml_master_crc32(pb, &dyn_cp, mkv); |
|
|
|
|
|
|
|
|
end_ebml_master_crc32(pb, &dyn_cp, mkv, MATROSKA_ID_CUES); |
|
|
|
|
|
|
|
|
return currentpos; |
|
|
return currentpos; |
|
|
} |
|
|
} |
|
|
@@ -1372,7 +1373,7 @@ static int mkv_write_tracks(AVFormatContext *s) |
|
|
|
|
|
|
|
|
mkv_add_seekhead_entry(mkv, MATROSKA_ID_TRACKS, avio_tell(pb)); |
|
|
mkv_add_seekhead_entry(mkv, MATROSKA_ID_TRACKS, avio_tell(pb)); |
|
|
|
|
|
|
|
|
ret = start_ebml_master_crc32(pb, &mkv->tracks_bc, mkv, MATROSKA_ID_TRACKS); |
|
|
|
|
|
|
|
|
ret = start_ebml_master_crc32(&mkv->tracks_bc, mkv); |
|
|
if (ret < 0) |
|
|
if (ret < 0) |
|
|
return ret; |
|
|
return ret; |
|
|
|
|
|
|
|
|
@@ -1387,9 +1388,10 @@ static int mkv_write_tracks(AVFormatContext *s) |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
if ((pb->seekable & AVIO_SEEKABLE_NORMAL) && !mkv->is_live) |
|
|
if ((pb->seekable & AVIO_SEEKABLE_NORMAL) && !mkv->is_live) |
|
|
end_ebml_master_crc32_preliminary(pb, &mkv->tracks_bc, mkv, &mkv->tracks_pos); |
|
|
|
|
|
|
|
|
end_ebml_master_crc32_preliminary(pb, &mkv->tracks_bc, mkv, |
|
|
|
|
|
MATROSKA_ID_TRACKS, &mkv->tracks_pos); |
|
|
else |
|
|
else |
|
|
end_ebml_master_crc32(pb, &mkv->tracks_bc, mkv); |
|
|
|
|
|
|
|
|
end_ebml_master_crc32(pb, &mkv->tracks_bc, mkv, MATROSKA_ID_TRACKS); |
|
|
|
|
|
|
|
|
return 0; |
|
|
return 0; |
|
|
} |
|
|
} |
|
|
@@ -1407,7 +1409,7 @@ static int mkv_write_chapters(AVFormatContext *s) |
|
|
|
|
|
|
|
|
mkv_add_seekhead_entry(mkv, MATROSKA_ID_CHAPTERS, avio_tell(pb)); |
|
|
mkv_add_seekhead_entry(mkv, MATROSKA_ID_CHAPTERS, avio_tell(pb)); |
|
|
|
|
|
|
|
|
ret = start_ebml_master_crc32(pb, &dyn_cp, mkv, MATROSKA_ID_CHAPTERS); |
|
|
|
|
|
|
|
|
ret = start_ebml_master_crc32(&dyn_cp, mkv); |
|
|
if (ret < 0) return ret; |
|
|
if (ret < 0) return ret; |
|
|
|
|
|
|
|
|
editionentry = start_ebml_master(dyn_cp, MATROSKA_ID_EDITIONENTRY, 0); |
|
|
editionentry = start_ebml_master(dyn_cp, MATROSKA_ID_EDITIONENTRY, 0); |
|
|
@@ -1445,7 +1447,7 @@ static int mkv_write_chapters(AVFormatContext *s) |
|
|
end_ebml_master(dyn_cp, chapteratom); |
|
|
end_ebml_master(dyn_cp, chapteratom); |
|
|
} |
|
|
} |
|
|
end_ebml_master(dyn_cp, editionentry); |
|
|
end_ebml_master(dyn_cp, editionentry); |
|
|
end_ebml_master_crc32(pb, &dyn_cp, mkv); |
|
|
|
|
|
|
|
|
end_ebml_master_crc32(pb, &dyn_cp, mkv, MATROSKA_ID_CHAPTERS); |
|
|
|
|
|
|
|
|
mkv->wrote_chapters = 1; |
|
|
mkv->wrote_chapters = 1; |
|
|
return 0; |
|
|
return 0; |
|
|
@@ -1496,7 +1498,7 @@ static int mkv_write_tag_targets(AVFormatContext *s, uint32_t elementid, |
|
|
if (!mkv->tags_bc) { |
|
|
if (!mkv->tags_bc) { |
|
|
mkv_add_seekhead_entry(mkv, MATROSKA_ID_TAGS, avio_tell(s->pb)); |
|
|
mkv_add_seekhead_entry(mkv, MATROSKA_ID_TAGS, avio_tell(s->pb)); |
|
|
|
|
|
|
|
|
ret = start_ebml_master_crc32(s->pb, &mkv->tags_bc, mkv, MATROSKA_ID_TAGS); |
|
|
|
|
|
|
|
|
ret = start_ebml_master_crc32(&mkv->tags_bc, mkv); |
|
|
if (ret < 0) |
|
|
if (ret < 0) |
|
|
return ret; |
|
|
return ret; |
|
|
} |
|
|
} |
|
|
@@ -1641,9 +1643,10 @@ static int mkv_write_tags(AVFormatContext *s) |
|
|
|
|
|
|
|
|
if (mkv->tags_bc) { |
|
|
if (mkv->tags_bc) { |
|
|
if ((s->pb->seekable & AVIO_SEEKABLE_NORMAL) && !mkv->is_live) |
|
|
if ((s->pb->seekable & AVIO_SEEKABLE_NORMAL) && !mkv->is_live) |
|
|
end_ebml_master_crc32_preliminary(s->pb, &mkv->tags_bc, mkv, &mkv->tags_pos); |
|
|
|
|
|
|
|
|
end_ebml_master_crc32_preliminary(s->pb, &mkv->tags_bc, mkv, |
|
|
|
|
|
MATROSKA_ID_TAGS, &mkv->tags_pos); |
|
|
else |
|
|
else |
|
|
end_ebml_master_crc32(s->pb, &mkv->tags_bc, mkv); |
|
|
|
|
|
|
|
|
end_ebml_master_crc32(s->pb, &mkv->tags_bc, mkv, MATROSKA_ID_TAGS); |
|
|
} |
|
|
} |
|
|
return 0; |
|
|
return 0; |
|
|
} |
|
|
} |
|
|
@@ -1666,7 +1669,7 @@ static int mkv_write_attachments(AVFormatContext *s) |
|
|
|
|
|
|
|
|
mkv_add_seekhead_entry(mkv, MATROSKA_ID_ATTACHMENTS, avio_tell(pb)); |
|
|
mkv_add_seekhead_entry(mkv, MATROSKA_ID_ATTACHMENTS, avio_tell(pb)); |
|
|
|
|
|
|
|
|
ret = start_ebml_master_crc32(pb, &dyn_cp, mkv, MATROSKA_ID_ATTACHMENTS); |
|
|
|
|
|
|
|
|
ret = start_ebml_master_crc32(&dyn_cp, mkv); |
|
|
if (ret < 0) return ret; |
|
|
if (ret < 0) return ret; |
|
|
|
|
|
|
|
|
for (i = 0; i < s->nb_streams; i++) { |
|
|
for (i = 0; i < s->nb_streams; i++) { |
|
|
@@ -1739,7 +1742,7 @@ static int mkv_write_attachments(AVFormatContext *s) |
|
|
mkv->attachments->entries[mkv->attachments->num_entries].stream_idx = i; |
|
|
mkv->attachments->entries[mkv->attachments->num_entries].stream_idx = i; |
|
|
mkv->attachments->entries[mkv->attachments->num_entries++].fileuid = fileuid; |
|
|
mkv->attachments->entries[mkv->attachments->num_entries++].fileuid = fileuid; |
|
|
} |
|
|
} |
|
|
end_ebml_master_crc32(pb, &dyn_cp, mkv); |
|
|
|
|
|
|
|
|
end_ebml_master_crc32(pb, &dyn_cp, mkv, MATROSKA_ID_ATTACHMENTS); |
|
|
|
|
|
|
|
|
return 0; |
|
|
return 0; |
|
|
} |
|
|
} |
|
|
@@ -1818,7 +1821,7 @@ static int mkv_write_header(AVFormatContext *s) |
|
|
|
|
|
|
|
|
mkv_add_seekhead_entry(mkv, MATROSKA_ID_INFO, avio_tell(pb)); |
|
|
mkv_add_seekhead_entry(mkv, MATROSKA_ID_INFO, avio_tell(pb)); |
|
|
|
|
|
|
|
|
ret = start_ebml_master_crc32(pb, &mkv->info_bc, mkv, MATROSKA_ID_INFO); |
|
|
|
|
|
|
|
|
ret = start_ebml_master_crc32(&mkv->info_bc, mkv); |
|
|
if (ret < 0) |
|
|
if (ret < 0) |
|
|
return ret; |
|
|
return ret; |
|
|
pb = mkv->info_bc; |
|
|
pb = mkv->info_bc; |
|
|
@@ -1877,9 +1880,10 @@ static int mkv_write_header(AVFormatContext *s) |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
if ((s->pb->seekable & AVIO_SEEKABLE_NORMAL) && !mkv->is_live) |
|
|
if ((s->pb->seekable & AVIO_SEEKABLE_NORMAL) && !mkv->is_live) |
|
|
end_ebml_master_crc32_preliminary(s->pb, &mkv->info_bc, mkv, &mkv->info_pos); |
|
|
|
|
|
|
|
|
end_ebml_master_crc32_preliminary(s->pb, &mkv->info_bc, mkv, |
|
|
|
|
|
MATROSKA_ID_INFO, &mkv->info_pos); |
|
|
else |
|
|
else |
|
|
end_ebml_master_crc32(s->pb, &mkv->info_bc, mkv); |
|
|
|
|
|
|
|
|
end_ebml_master_crc32(s->pb, &mkv->info_bc, mkv, MATROSKA_ID_INFO); |
|
|
pb = s->pb; |
|
|
pb = s->pb; |
|
|
|
|
|
|
|
|
ret = mkv_write_tracks(s); |
|
|
ret = mkv_write_tracks(s); |
|
|
@@ -2167,7 +2171,7 @@ static void mkv_end_cluster(AVFormatContext *s) |
|
|
{ |
|
|
{ |
|
|
MatroskaMuxContext *mkv = s->priv_data; |
|
|
MatroskaMuxContext *mkv = s->priv_data; |
|
|
|
|
|
|
|
|
end_ebml_master_crc32(s->pb, &mkv->cluster_bc, mkv); |
|
|
|
|
|
|
|
|
end_ebml_master_crc32(s->pb, &mkv->cluster_bc, mkv, MATROSKA_ID_CLUSTER); |
|
|
mkv->cluster_pos = -1; |
|
|
mkv->cluster_pos = -1; |
|
|
avio_write_marker(s->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_FLUSH_POINT); |
|
|
avio_write_marker(s->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_FLUSH_POINT); |
|
|
} |
|
|
} |
|
|
@@ -2308,7 +2312,7 @@ static int mkv_write_packet_internal(AVFormatContext *s, AVPacket *pkt, int add_ |
|
|
|
|
|
|
|
|
if (mkv->cluster_pos == -1) { |
|
|
if (mkv->cluster_pos == -1) { |
|
|
mkv->cluster_pos = avio_tell(s->pb); |
|
|
mkv->cluster_pos = avio_tell(s->pb); |
|
|
ret = start_ebml_master_crc32(s->pb, &mkv->cluster_bc, mkv, MATROSKA_ID_CLUSTER); |
|
|
|
|
|
|
|
|
ret = start_ebml_master_crc32(&mkv->cluster_bc, mkv); |
|
|
if (ret < 0) |
|
|
if (ret < 0) |
|
|
return ret; |
|
|
return ret; |
|
|
put_ebml_uint(mkv->cluster_bc, MATROSKA_ID_CLUSTERTIMECODE, FFMAX(0, ts)); |
|
|
put_ebml_uint(mkv->cluster_bc, MATROSKA_ID_CLUSTERTIMECODE, FFMAX(0, ts)); |
|
|
@@ -2474,7 +2478,7 @@ static int mkv_write_trailer(AVFormatContext *s) |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
if (mkv->cluster_bc) { |
|
|
if (mkv->cluster_bc) { |
|
|
end_ebml_master_crc32(pb, &mkv->cluster_bc, mkv); |
|
|
|
|
|
|
|
|
end_ebml_master_crc32(pb, &mkv->cluster_bc, mkv, MATROSKA_ID_CLUSTER); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
ret = mkv_write_chapters(s); |
|
|
ret = mkv_write_chapters(s); |
|
|
@@ -2522,11 +2526,11 @@ static int mkv_write_trailer(AVFormatContext *s) |
|
|
av_log(s, AV_LOG_DEBUG, "end duration = %" PRIu64 "\n", mkv->duration); |
|
|
av_log(s, AV_LOG_DEBUG, "end duration = %" PRIu64 "\n", mkv->duration); |
|
|
avio_seek(mkv->info_bc, mkv->duration_offset, SEEK_SET); |
|
|
avio_seek(mkv->info_bc, mkv->duration_offset, SEEK_SET); |
|
|
put_ebml_float(mkv->info_bc, MATROSKA_ID_DURATION, mkv->duration); |
|
|
put_ebml_float(mkv->info_bc, MATROSKA_ID_DURATION, mkv->duration); |
|
|
end_ebml_master_crc32(pb, &mkv->info_bc, mkv); |
|
|
|
|
|
|
|
|
end_ebml_master_crc32(pb, &mkv->info_bc, mkv, MATROSKA_ID_INFO); |
|
|
|
|
|
|
|
|
// write tracks master |
|
|
// write tracks master |
|
|
avio_seek(pb, mkv->tracks_pos, SEEK_SET); |
|
|
avio_seek(pb, mkv->tracks_pos, SEEK_SET); |
|
|
end_ebml_master_crc32(pb, &mkv->tracks_bc, mkv); |
|
|
|
|
|
|
|
|
end_ebml_master_crc32(pb, &mkv->tracks_bc, mkv, MATROSKA_ID_TRACKS); |
|
|
|
|
|
|
|
|
// update stream durations |
|
|
// update stream durations |
|
|
if (!mkv->is_live) { |
|
|
if (!mkv->is_live) { |
|
|
@@ -2556,7 +2560,7 @@ static int mkv_write_trailer(AVFormatContext *s) |
|
|
} |
|
|
} |
|
|
if (mkv->tags_bc && !mkv->is_live) { |
|
|
if (mkv->tags_bc && !mkv->is_live) { |
|
|
avio_seek(pb, mkv->tags_pos, SEEK_SET); |
|
|
avio_seek(pb, mkv->tags_pos, SEEK_SET); |
|
|
end_ebml_master_crc32(pb, &mkv->tags_bc, mkv); |
|
|
|
|
|
|
|
|
end_ebml_master_crc32(pb, &mkv->tags_bc, mkv, MATROSKA_ID_TAGS); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
avio_seek(pb, currentpos, SEEK_SET); |
|
|
avio_seek(pb, currentpos, SEEK_SET); |
|
|
|