MayaFlux 0.2.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches

◆ open()

bool MayaFlux::IO::VideoStreamContext::open ( const FFmpegDemuxContext demux,
uint32_t  target_width = 0,
uint32_t  target_height = 0,
int  target_format = -1 
)

Open the video stream from an already-probed demux context.

Finds the best video stream, allocates and opens the codec context, caches video parameters, and initialises the SwsContext for conversion to the target pixel format (default AV_PIX_FMT_RGBA).

Parameters
demuxOpen demux context (must outlive this object).
target_widthOutput width in pixels; 0 = keep source width.
target_heightOutput height in pixels; 0 = keep source height.
target_formatTarget AVPixelFormat; negative = AV_PIX_FMT_RGBA.
Returns
True on success.

Definition at line 52 of file VideoStreamContext.cpp.

56{
57 close();
59
60 if (!demux.is_open()) {
61 m_last_error = "Demux context is not open";
62 return false;
63 }
64
65 const AVCodec* codec = nullptr;
66 stream_index = demux.find_best_stream(AVMEDIA_TYPE_VIDEO,
67 reinterpret_cast<const void**>(&codec));
68 if (stream_index < 0 || !codec) {
69 m_last_error = "No video stream found";
70 return false;
71 }
72
73 codec_context = avcodec_alloc_context3(codec);
74 if (!codec_context) {
75 m_last_error = "avcodec_alloc_context3 failed";
76 return false;
77 }
78
79 AVStream* stream = demux.get_stream(stream_index);
80 if (avcodec_parameters_to_context(codec_context, stream->codecpar) < 0) {
81 m_last_error = "avcodec_parameters_to_context failed";
82 close();
83 return false;
84 }
85
86 if (avcodec_open2(codec_context, codec, nullptr) < 0) {
87 m_last_error = "avcodec_open2 failed";
88 close();
89 return false;
90 }
91
92#ifdef MAYAFLUX_PLATFORM_WINDOWS
93 uint32_t probed_width = 0;
94 uint32_t probed_height = 0;
95
96 if (codec_context->pix_fmt == AV_PIX_FMT_NONE) {
97 AVPacket* probe_pkt = av_packet_alloc();
98 AVFrame* probe_frm = av_frame_alloc();
99
100 if (probe_pkt && probe_frm) {
101 AVFormatContext* fmt = demux.format_context;
102 bool probed = false;
103
104 while (!probed && av_read_frame(fmt, probe_pkt) >= 0) {
105 if (probe_pkt->stream_index != stream_index) {
106 av_packet_unref(probe_pkt);
107 continue;
108 }
109 if (avcodec_send_packet(codec_context, probe_pkt) >= 0) {
110 if (avcodec_receive_frame(codec_context, probe_frm) >= 0) {
111 if (codec_context->pix_fmt == AV_PIX_FMT_NONE
112 && probe_frm->format != AV_PIX_FMT_NONE) {
113 codec_context->pix_fmt = static_cast<AVPixelFormat>(probe_frm->format);
114 }
115 probed_width = static_cast<uint32_t>(probe_frm->width);
116 probed_height = static_cast<uint32_t>(probe_frm->height);
117 probed = true;
118 av_frame_unref(probe_frm);
119 }
120 }
121 av_packet_unref(probe_pkt);
122 }
123 }
124
125 av_packet_free(&probe_pkt);
126 av_frame_free(&probe_frm);
127 avcodec_flush_buffers(codec_context);
128 }
129
130 width = static_cast<uint32_t>(codec_context->width);
131 height = static_cast<uint32_t>(codec_context->height);
132
133 if (probed_width > 0 && probed_height > 0) {
134 width = probed_width;
135 height = probed_height;
136 codec_context->width = static_cast<int>(width);
137 codec_context->height = static_cast<int>(height);
138 }
139#else
140 width = static_cast<uint32_t>(codec_context->width);
141 height = static_cast<uint32_t>(codec_context->height);
142#endif
143
144 if (codec_context->codec_id == AV_CODEC_ID_HEVC
145 && stream->r_frame_rate.den > 0
146 && stream->r_frame_rate.num > 0) {
147 frame_rate = av_q2d(stream->r_frame_rate);
148 } else if (stream->avg_frame_rate.den > 0 && stream->avg_frame_rate.num > 0) {
149 frame_rate = av_q2d(stream->avg_frame_rate);
150 } else if (stream->r_frame_rate.den > 0 && stream->r_frame_rate.num > 0) {
151 frame_rate = av_q2d(stream->r_frame_rate);
152 }
153
155
156 if (stream->nb_frames > 0) {
157 total_frames = static_cast<uint64_t>(stream->nb_frames);
158 } else if (stream->duration != AV_NOPTS_VALUE
159 && stream->time_base.num > 0 && stream->time_base.den > 0
160 && frame_rate > 0.0) {
161 double dur = static_cast<double>(stream->duration) * av_q2d(stream->time_base);
162 total_frames = static_cast<uint64_t>(dur * frame_rate);
163 } else if (demux.format_context->duration != AV_NOPTS_VALUE && frame_rate > 0.0) {
164 double dur = static_cast<double>(demux.format_context->duration)
165 / static_cast<double>(AV_TIME_BASE);
166 total_frames = static_cast<uint64_t>(dur * frame_rate);
167 }
168
170 "[VideoStreamContext] stream #{} | "
171 "avg_frame_rate={}/{} ({:.6f} fps) | "
172 "r_frame_rate={}/{} ({:.6f} fps) | "
173 "chosen frame_rate={:.6f} fps | "
174 "nb_frames={} | "
175 "stream duration={} (tb={}/{}, => {:.4f}s) | "
176 "format duration={} (=> {:.4f}s) | "
177 "total_frames={} | "
178 "source={}",
180 stream->avg_frame_rate.num, stream->avg_frame_rate.den,
181 (stream->avg_frame_rate.den > 0 ? av_q2d(stream->avg_frame_rate) : 0.0),
182 stream->r_frame_rate.num, stream->r_frame_rate.den,
183 (stream->r_frame_rate.den > 0 ? av_q2d(stream->r_frame_rate) : 0.0),
185 static_cast<int64_t>(stream->nb_frames),
186 stream->duration,
187 stream->time_base.num, stream->time_base.den,
188 (stream->duration != AV_NOPTS_VALUE && stream->time_base.den > 0
189 ? static_cast<double>(stream->duration) * av_q2d(stream->time_base)
190 : -1.0),
191 demux.format_context->duration,
192 (demux.format_context->duration != AV_NOPTS_VALUE
193 ? static_cast<double>(demux.format_context->duration) / AV_TIME_BASE
194 : -1.0),
196 (stream->nb_frames > 0 ? "nb_frames"
197 : (stream->duration != AV_NOPTS_VALUE ? "stream_duration*fps"
198 : "format_duration*fps")));
199
201 close();
202 return false;
203 }
204
205 return true;
206}
#define MF_INFO(comp, ctx,...)
static void init_ffmpeg()
Initialise FFmpeg logging level once per process.
uint32_t target_width
Requested output width (0 = source).
void close()
Release codec and scaler resources.
uint32_t target_height
Requested output height (0 = source).
double frame_rate
Average frame rate (fps).
bool setup_scaler(uint32_t target_width, uint32_t target_height, int target_format)
Allocate and initialise the SwsContext for pixel format conversion.
uint32_t height
Source height in pixels.
uint32_t width
Source width in pixels.
int src_pixel_format
Source AVPixelFormat.
AVCodecContext * codec_context
Owned; freed in destructor.
int target_format
Requested AVPixelFormat (negative = RGBA).
@ FileIO
Filesystem I/O operations.
@ IO
Networking, file handling, streaming.

References close(), codec_context, MayaFlux::Journal::FileIO, MayaFlux::IO::FFmpegDemuxContext::find_best_stream(), MayaFlux::IO::FFmpegDemuxContext::format_context, frame_rate, MayaFlux::IO::FFmpegDemuxContext::get_stream(), height, MayaFlux::IO::FFmpegDemuxContext::init_ffmpeg(), MayaFlux::Journal::IO, MayaFlux::IO::FFmpegDemuxContext::is_open(), m_last_error, MF_INFO, setup_scaler(), src_pixel_format, stream_index, target_format, target_height, target_width, total_frames, and width.

+ Here is the call graph for this function: