MayaFlux 0.4.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
FFmpegMuxContext.cpp
Go to the documentation of this file.
3
4#include "FileWriter.hpp"
5
6extern "C" {
7#include <libavformat/avformat.h>
8#include <libavutil/error.h>
9}
10
11namespace MayaFlux::IO {
12
13// =========================================================================
14// Destructor
15// =========================================================================
16
21
22// =========================================================================
23// Lifecycle
24// =========================================================================
25
26bool FFmpegMuxContext::open(const std::string& filepath,
27 const std::string& explicit_format)
28{
29 close();
31
32 const char* fmt = explicit_format.empty() ? nullptr : explicit_format.c_str();
33
34 const auto resolved = resolve_write_path(filepath);
35
36 int ret = avformat_alloc_output_context2(
37 &format_context, nullptr, fmt, resolved.c_str());
38
39 if (ret < 0 || !format_context) {
40 char errbuf[AV_ERROR_MAX_STRING_SIZE];
41 av_strerror(ret, errbuf, sizeof(errbuf));
42 m_last_error = "avformat_alloc_output_context2 failed for \""
43 + resolved + "\": " + errbuf;
44 return false;
45 }
46
47 if (!(format_context->oformat->flags & AVFMT_NOFILE)) {
48 ret = avio_open(&format_context->pb, resolved.c_str(), AVIO_FLAG_WRITE);
49 if (ret < 0) {
50 char errbuf[AV_ERROR_MAX_STRING_SIZE];
51 av_strerror(ret, errbuf, sizeof(errbuf));
52 m_last_error = "avio_open failed for \""
53 + resolved + "\": " + errbuf;
54 avformat_free_context(format_context);
55 format_context = nullptr;
56 return false;
57 }
58 }
59
60 return true;
61}
62
64{
65 if (!format_context)
66 return;
67
68 if (m_header_written) {
69 av_write_trailer(format_context);
70 m_header_written = false;
71 }
72
73 if (format_context->pb && !(format_context->oformat->flags & AVFMT_NOFILE))
74 avio_closep(&format_context->pb);
75
76 avformat_free_context(format_context);
77 format_context = nullptr;
78 m_last_error.clear();
79}
80
81// =========================================================================
82// Stream registration
83// =========================================================================
84
86{
87 if (!format_context) {
88 m_last_error = "add_stream called on unopened context";
89 return nullptr;
90 }
91 AVStream* st = avformat_new_stream(format_context, nullptr);
92 if (!st)
93 m_last_error = "avformat_new_stream failed";
94 return st;
95}
96
97// =========================================================================
98// Header / packet writing
99// =========================================================================
100
102{
103 if (!format_context) {
104 m_last_error = "write_header called on unopened context";
105 return false;
106 }
107 if (m_header_written) {
108 m_last_error = "write_header called more than once";
109 return false;
110 }
111
112 int ret = avformat_write_header(format_context, nullptr);
113 if (ret < 0) {
114 char errbuf[AV_ERROR_MAX_STRING_SIZE];
115 av_strerror(ret, errbuf, sizeof(errbuf));
116 m_last_error = std::string("avformat_write_header failed: ") + errbuf;
117 return false;
118 }
119
120 m_header_written = true;
121 return true;
122}
123
125{
127 m_last_error = "write_packet called before header was written";
128 return false;
129 }
130
131 int ret = av_interleaved_write_frame(format_context, pkt);
132 if (ret < 0) {
133 char errbuf[AV_ERROR_MAX_STRING_SIZE];
134 av_strerror(ret, errbuf, sizeof(errbuf));
135 m_last_error = std::string("av_interleaved_write_frame failed: ") + errbuf;
136 return false;
137 }
138
139 return true;
140}
141
142} // namespace MayaFlux::IO
static void init_ffmpeg()
Initialise FFmpeg logging level once per process.
AVStream * add_stream()
Allocate a new AVStream inside this context.
bool open(const std::string &filepath, const std::string &explicit_format={})
Allocate an output context and open the avio layer for writing.
bool write_header()
Write the container header to the output file.
void close()
Write the container trailer, flush avio, and release all resources.
bool write_packet(AVPacket *pkt)
Submit one encoded packet for interleaved writing.
AVFormatContext * format_context
Owned; freed in close().
std::string resolve_write_path(const std::string &filepath)
Anchor a relative output path to Config::SOURCE_DIR.