Write the file header (after the options are set)
| 628 | |
| 629 | // Write the file header (after the options are set) |
| 630 | void FFmpegWriter::WriteHeader() { |
| 631 | if (!info.has_audio && !info.has_video) |
| 632 | throw InvalidOptions("No video or audio options have been set. You must set has_video or has_audio (or both).", path); |
| 633 | |
| 634 | // Open the output file, if needed |
| 635 | if (!(oc->oformat->flags & AVFMT_NOFILE)) { |
| 636 | if (avio_open(&oc->pb, path.c_str(), AVIO_FLAG_WRITE) < 0) |
| 637 | throw InvalidFile("Could not open or write file.", path); |
| 638 | } |
| 639 | |
| 640 | // Force the output filename (which doesn't always happen for some reason) |
| 641 | AV_SET_FILENAME(oc, path.c_str()); |
| 642 | |
| 643 | // Add general metadata (if any) |
| 644 | for (auto iter = info.metadata.begin(); iter != info.metadata.end(); ++iter) { |
| 645 | av_dict_set(&oc->metadata, iter->first.c_str(), iter->second.c_str(), 0); |
| 646 | } |
| 647 | |
| 648 | // Set multiplexing parameters (only for MP4/MOV containers) |
| 649 | AVDictionary *dict = NULL; |
| 650 | if (mux_dict) { |
| 651 | av_dict_copy(&dict, mux_dict, 0); |
| 652 | } |
| 653 | |
| 654 | // Write the stream header |
| 655 | if (avformat_write_header(oc, &dict) != 0) { |
| 656 | ZmqLogger::Instance()->AppendDebugMethod( |
| 657 | "FFmpegWriter::WriteHeader (avformat_write_header)"); |
| 658 | throw InvalidFile("Could not write header to file.", path); |
| 659 | }; |
| 660 | |
| 661 | // Free multiplexing dictionaries sets |
| 662 | if (dict) av_dict_free(&dict); |
| 663 | if (mux_dict) av_dict_free(&mux_dict); |
| 664 | |
| 665 | // Mark as 'written' |
| 666 | write_header = true; |
| 667 | |
| 668 | ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::WriteHeader"); |
| 669 | } |
| 670 | |
| 671 | // Add a frame to the queue waiting to be encoded. |
| 672 | void FFmpegWriter::WriteFrame(std::shared_ptr<openshot::Frame> frame) { |
no test coverage detected