@@ -41,6 +41,9 @@ using namespace openshot;
4141#pragma message "You are compiling only with software encode"
4242#endif
4343
44+ // Multiplexer parameters temporary storage
45+ AVDictionary *mux_dict = NULL ;
46+
4447#if IS_FFMPEG_3_2
4548int hw_en_on = 1 ; // Is set in UI
4649int hw_en_supported = 0 ; // Is set by FFmpegWriter
@@ -467,6 +470,17 @@ void FFmpegWriter::SetOption(StreamType stream, string name, string value) {
467470
468471 ZmqLogger::Instance ()->AppendDebugMethod (" FFmpegWriter::SetOption (" + (string)name + " )" , " stream == VIDEO_STREAM" , stream == VIDEO_STREAM, " " , -1 , " " , -1 , " " , -1 , " " , -1 , " " , -1 );
469472
473+ // Muxing dictionary is not part of the codec context.
474+ // Just reusing SetOption function to set popular multiplexing presets.
475+ } else if (name == " muxing_preset" ) {
476+ if (value == " mp4_faststart" ) {
477+ // 'moov' box to the beginning; only for MOV, MP4
478+ av_dict_set (&mux_dict, " movflags" , " faststart" , 0 );
479+ } else if (value == " mp4_fragmented" ) {
480+ // write selfcontained fragmented file, minimum length of the fragment 8 sec; only for MOV, MP4
481+ av_dict_set (&mux_dict, " movflags" , " frag_keyframe" , 0 );
482+ av_dict_set (&mux_dict, " min_frag_duration" , " 8000000" , 0 );
483+ }
470484 } else {
471485 throw InvalidOptions (" The option is not valid for this codec." , path);
472486 }
@@ -514,17 +528,29 @@ void FFmpegWriter::WriteHeader() {
514528 snprintf (oc->AV_FILENAME , sizeof (oc->AV_FILENAME ), " %s" , path.c_str ());
515529
516530 // Write the stream header, if any
517- // TODO: add avoptions / parameters instead of NULL
518531
519532 // Add general metadata (if any)
520533 for (std::map<string, string>::iterator iter = info.metadata .begin (); iter != info.metadata .end (); ++iter) {
521534 av_dict_set (&oc->metadata , iter->first .c_str (), iter->second .c_str (), 0 );
522535 }
523536
524- if (avformat_write_header (oc, NULL ) != 0 ) {
537+ // Set multiplexing parameters
538+ AVDictionary *dict = NULL ;
539+
540+ bool is_mp4 = strcmp (oc->oformat ->name , " mp4" );
541+ bool is_mov = strcmp (oc->oformat ->name , " mov" );
542+ // Set dictionary preset only for MP4 and MOV files
543+ if (is_mp4 || is_mov)
544+ av_dict_copy (&dict, mux_dict, 0 );
545+
546+ if (avformat_write_header (oc, &dict) != 0 ) {
525547 throw InvalidFile (" Could not write header to file." , path);
526548 };
527549
550+ // Free multiplexing dictionaries sets
551+ if (dict) av_dict_free (&dict);
552+ if (mux_dict) av_dict_free (&mux_dict);
553+
528554 // Mark as 'written'
529555 write_header = true ;
530556
0 commit comments