Skip to content

Commit be7db11

Browse files
author
SuslikV
authored
Add streamable file format options for mp4, mov
Add 2 new multiplexing presets for mp4, mov files: mp4_faststart mp4_fragmented The Preset usage from openshot-qt export.py as follows (example): w.SetOption(openshot.VIDEO_STREAM, "muxing_preset", "mp4_faststart") YouTube suggest to use streamable file formats to process the uploading videos faster (by starting its processing when upload not yet complete) MP4, MOV files export requires additional dictionary keys to be set in this case.
1 parent 0d4ea7f commit be7db11

File tree

1 file changed

+28
-2
lines changed

1 file changed

+28
-2
lines changed

src/FFmpegWriter.cpp

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ using namespace openshot;
3838
#pragma message "You are compiling only with software encode"
3939
#endif
4040

41+
// Multiplexer parameters temporary storage
42+
AVDictionary *mux_dict = NULL;
43+
4144
#if IS_FFMPEG_3_2
4245
int hw_en_on = 1; // Is set in UI
4346
int hw_en_supported = 0; // Is set by FFmpegWriter
@@ -464,6 +467,17 @@ void FFmpegWriter::SetOption(StreamType stream, string name, string value) {
464467

465468
ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::SetOption (" + (string)name + ")", "stream == VIDEO_STREAM", stream == VIDEO_STREAM, "", -1, "", -1, "", -1, "", -1, "", -1);
466469

470+
// Muxing dictionary is not part of the codec context.
471+
// Just reusing SetOption function to set popular multiplexing presets.
472+
} else if (name == "muxing_preset") {
473+
if (value == "mp4_faststart") {
474+
// 'moov' box to the beginning; only for MOV, MP4
475+
av_dict_set(&mux_dict, "movflags", "faststart", 0);
476+
} else if (value == "mp4_fragmented") {
477+
// write selfcontained fragmented file, minimum length of the fragment 8 sec; only for MOV, MP4
478+
av_dict_set(&mux_dict, "movflags", "frag_keyframe", 0);
479+
av_dict_set(&mux_dict, "min_frag_duration", "8000000", 0);
480+
}
467481
} else {
468482
throw InvalidOptions("The option is not valid for this codec.", path);
469483
}
@@ -511,17 +525,29 @@ void FFmpegWriter::WriteHeader() {
511525
snprintf(oc->AV_FILENAME, sizeof(oc->AV_FILENAME), "%s", path.c_str());
512526

513527
// Write the stream header, if any
514-
// TODO: add avoptions / parameters instead of NULL
515528

516529
// Add general metadata (if any)
517530
for (std::map<string, string>::iterator iter = info.metadata.begin(); iter != info.metadata.end(); ++iter) {
518531
av_dict_set(&oc->metadata, iter->first.c_str(), iter->second.c_str(), 0);
519532
}
520533

521-
if (avformat_write_header(oc, NULL) != 0) {
534+
// Set multiplexing parameters
535+
AVDictionary *dict = NULL;
536+
537+
bool is_mp4 = strcmp(oc->oformat->name, "mp4");
538+
bool is_mov = strcmp(oc->oformat->name, "mov");
539+
// Set dictionary preset only for MP4 and MOV files
540+
if (is_mp4 || is_mov)
541+
av_dict_copy(&dict, mux_dict, 0);
542+
543+
if (avformat_write_header(oc, &dict) != 0) {
522544
throw InvalidFile("Could not write header to file.", path);
523545
};
524546

547+
// Free multiplexing dictionaries sets
548+
if (dict) av_dict_free(&dict);
549+
if (mux_dict) av_dict_free(&mux_dict);
550+
525551
// Mark as 'written'
526552
write_header = true;
527553

0 commit comments

Comments
 (0)