Commit 9e0b0c60 authored by Michael Niedermayer's avatar Michael Niedermayer

Merge commit '2ded5737'

* commit '2ded5737':
  movenc: Add support for writing sidx atoms for DASH segments

Conflicts:
	Changelog
	libavformat/version.h
Merged-by: 's avatarMichael Niedermayer <michaelni@gmx.at>
parents 1fddfaa2 2ded5737
......@@ -13,6 +13,7 @@ version <next>:
- xBR scaling filter
- AVFoundation screen capturing support
- ffserver supports codec private options
- creating DASH compatible fragmented MP4
version 2.4:
- Icecast protocol
......
......@@ -64,6 +64,7 @@ static const AVOption options[] = {
{ "omit_tfhd_offset", "Omit the base data offset in tfhd atoms", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_OMIT_TFHD_OFFSET}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
{ "disable_chpl", "Disable Nero chapter atom", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_DISABLE_CHPL}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
{ "default_base_moof", "Set the default-base-is-moof flag in tfhd atoms", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_DEFAULT_BASE_MOOF}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
{ "dash", "Write DASH compatible fragmented MP4", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_DASH}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
FF_RTP_FLAG_OPTS(MOVMuxContext, rtp_flags),
{ "skip_iods", "Skip writing iods atom.", offsetof(MOVMuxContext, iods_skip), AV_OPT_TYPE_INT, {.i64 = 1}, 0, 1, AV_OPT_FLAG_ENCODING_PARAM},
{ "iods_audio_profile", "iods audio profile atom.", offsetof(MOVMuxContext, iods_audio_profile), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 255, AV_OPT_FLAG_ENCODING_PARAM},
......@@ -3405,7 +3406,78 @@ static int mov_write_moof_tag_internal(AVIOContext *pb, MOVMuxContext *mov,
return update_size(pb, pos);
}
static int mov_write_moof_tag(AVIOContext *pb, MOVMuxContext *mov, int tracks)
static int mov_write_sidx_tag(AVIOContext *pb,
MOVTrack *track, int ref_size, int total_sidx_size)
{
int64_t pos = avio_tell(pb), offset_pos, end_pos;
int64_t presentation_time = track->start_dts + track->frag_start +
track->cluster[0].cts;
int64_t duration = track->start_dts + track->track_duration -
track->cluster[0].dts;
int64_t offset;
int starts_with_SAP = track->cluster[0].flags & MOV_SYNC_SAMPLE;
// pts<0 should be cut away using edts
if (presentation_time < 0)
presentation_time = 0;
avio_wb32(pb, 0); /* size */
ffio_wfourcc(pb, "sidx");
avio_w8(pb, 1); /* version */
avio_wb24(pb, 0);
avio_wb32(pb, track->track_id); /* reference_ID */
avio_wb32(pb, track->timescale); /* timescale */
avio_wb64(pb, presentation_time); /* earliest_presentation_time */
offset_pos = avio_tell(pb);
avio_wb64(pb, 0); /* first_offset (offset to referenced moof) */
avio_wb16(pb, 0); /* reserved */
avio_wb16(pb, 1); /* reference_count */
avio_wb32(pb, (0 << 31) | (ref_size & 0x7fffffff)); /* reference_type (0 = media) | referenced_size */
avio_wb32(pb, duration); /* subsegment_duration */
avio_wb32(pb, (starts_with_SAP << 31) | (0 << 28) | 0); /* starts_with_SAP | SAP_type | SAP_delta_time */
end_pos = avio_tell(pb);
offset = pos + total_sidx_size - end_pos;
avio_seek(pb, offset_pos, SEEK_SET);
avio_wb64(pb, offset);
avio_seek(pb, end_pos, SEEK_SET);
return update_size(pb, pos);
}
static int mov_write_sidx_tags(AVIOContext *pb, MOVMuxContext *mov,
int tracks, int ref_size)
{
int i, round, ret;
AVIOContext *avio_buf;
int total_size = 0;
for (round = 0; round < 2; round++) {
// First run one round to calculate the total size of all
// sidx atoms.
// This would be much simpler if we'd only write one sidx
// atom, for the first track in the moof.
if (round == 0) {
if ((ret = ffio_open_null_buf(&avio_buf)) < 0)
return ret;
} else {
avio_buf = pb;
}
for (i = 0; i < mov->nb_streams; i++) {
MOVTrack *track = &mov->tracks[i];
if (tracks >= 0 && i != tracks)
continue;
if (!track->entry)
continue;
total_size -= mov_write_sidx_tag(avio_buf, track, ref_size,
total_size);
}
if (round == 0)
total_size = ffio_close_null_buf(avio_buf);
}
return 0;
}
static int mov_write_moof_tag(AVIOContext *pb, MOVMuxContext *mov, int tracks,
int64_t mdat_size)
{
AVIOContext *avio_buf;
int ret, moof_size;
......@@ -3415,6 +3487,9 @@ static int mov_write_moof_tag(AVIOContext *pb, MOVMuxContext *mov, int tracks)
mov_write_moof_tag_internal(avio_buf, mov, tracks, 0);
moof_size = ffio_close_null_buf(avio_buf);
if (mov->flags & FF_MOV_FLAG_DASH)
mov_write_sidx_tags(pb, mov, tracks, moof_size + 8 + mdat_size);
if ((ret = mov_add_tfra_entries(pb, mov, tracks)) < 0)
return ret;
......@@ -3779,7 +3854,7 @@ static int mov_flush_fragment(AVFormatContext *s)
if (write_moof) {
avio_flush(s->pb);
mov_write_moof_tag(s->pb, mov, moof_tracks);
mov_write_moof_tag(s->pb, mov, moof_tracks, mdat_size);
mov->fragments++;
avio_wb32(s->pb, mdat_size + 8);
......@@ -4423,6 +4498,9 @@ static int mov_write_header(AVFormatContext *s)
if (mov->mode == MODE_ISM)
mov->flags |= FF_MOV_FLAG_EMPTY_MOOV | FF_MOV_FLAG_SEPARATE_MOOF |
FF_MOV_FLAG_FRAGMENT;
if (mov->flags & FF_MOV_FLAG_DASH)
mov->flags |= FF_MOV_FLAG_FRAGMENT | FF_MOV_FLAG_EMPTY_MOOV |
FF_MOV_FLAG_DEFAULT_BASE_MOOF;
/* faststart: moov at the beginning of the file, if supported */
if (mov->flags & FF_MOV_FLAG_FASTSTART) {
......
......@@ -196,6 +196,7 @@ typedef struct MOVMuxContext {
#define FF_MOV_FLAG_OMIT_TFHD_OFFSET (1 << 8)
#define FF_MOV_FLAG_DISABLE_CHPL (1 << 9)
#define FF_MOV_FLAG_DEFAULT_BASE_MOOF (1 << 10)
#define FF_MOV_FLAG_DASH (1 << 11)
int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt);
......
......@@ -31,7 +31,7 @@
#define LIBAVFORMAT_VERSION_MAJOR 56
#define LIBAVFORMAT_VERSION_MINOR 13
#define LIBAVFORMAT_VERSION_MICRO 100
#define LIBAVFORMAT_VERSION_MICRO 101
#define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
LIBAVFORMAT_VERSION_MINOR, \
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment