Load file data into an existing container.
255{
256 if (!container) {
258 return false;
259 }
260
261 auto vc = std::dynamic_pointer_cast<Kakshya::VideoFileContainer>(container);
262 if (!vc) {
263 set_error(
"Container is not a VideoFileContainer");
264 return false;
265 }
266
267 std::shared_ptr<VideoStreamContext> video;
268 std::shared_ptr<AudioStreamContext> audio;
269 std::shared_ptr<FFmpegDemuxContext> demux;
270 {
274 return false;
275 }
279 }
280
283 vc->set_source_format(
m_demux->format_context->iformat->name);
284
285 const uint64_t total = video->total_frames;
286 if (total == 0) {
287 set_error(
"Video stream reports 0 frames");
288 return false;
289 }
290
291 const uint32_t ring_cap = std::min(
293 static_cast<uint32_t>(total));
294
297 : ring_cap / 4;
298
299 vc->setup_ring(total, ring_cap,
300 video->out_width, video->out_height,
301 video->out_bytes_per_pixel, video->frame_rate,
303
305 static_cast<size_t>(video->out_linesize) * video->out_height);
306
309 && demux->find_best_stream(AVMEDIA_TYPE_AUDIO) >= 0;
310
311 if (want_audio && audio && audio->is_valid()) {
312 {
314 demux->seek(audio->stream_index, 0);
315 audio->flush_codec();
316 audio->drain_resampler_init();
317 }
318
319 SoundFileReader audio_reader;
322
324 auto sc = audio_reader.create_container();
325 if (audio_reader.load_into_container(sc)) {
327 } else {
329 "VideoFileReader: audio load failed: {}",
330 audio_reader.get_last_error());
331 }
332 } else {
334 "VideoFileReader: open_from_demux failed: {}",
335 audio_reader.get_last_error());
336 }
337
338 {
340 demux->seek(video->stream_index, 0);
341 video->flush_codec();
342 }
343 }
344
347
348 const uint64_t preload = std::min(
349 static_cast<uint64_t>(ring_cap),
350 total);
351
353
354 if (decoded == 0) {
355 set_error(
"Failed to decode any frames during preload");
356 return false;
357 }
358
360 "VideoFileReader: preloaded {}/{} frames ({}x{}, {:.1f} fps, ring={})",
361 decoded, total,
362 video->out_width, video->out_height,
363 video->frame_rate, ring_cap);
364
367 for (const auto& [name, group] : region_groups)
369
370 vc->create_default_processor();
371 vc->mark_ready_for_processing(true);
372
373 if (decoded < total)
375
376 return true;
377}
#define MF_INFO(comp, ctx,...)
#define MF_WARN(comp, ctx,...)
static std::unordered_map< std::string, Kakshya::RegionGroup > regions_to_groups(const std::vector< FileRegion > ®ions)
Convert file regions to region groups.
uint64_t decode_batch(Kakshya::VideoFileContainer &vc, uint64_t batch_size)
Decode up to batch_size frames starting at m_decode_head.
void set_error(const std::string &msg) const
AudioReadOptions m_audio_options
void start_decode_thread()
std::vector< FileRegion > get_regions() const override
Get semantic regions from the file.
VideoReadOptions m_video_options
std::vector< uint8_t > m_sws_buf
One-frame sws scratch buffer (padded linesize, reused by decode thread).
std::weak_ptr< Kakshya::VideoFileContainer > m_container_ref
std::shared_ptr< FFmpegDemuxContext > m_demux
uint32_t m_target_sample_rate
FileReadOptions m_options
std::shared_mutex m_context_mutex
std::shared_ptr< VideoStreamContext > m_video
std::shared_ptr< AudioStreamContext > m_audio
std::shared_ptr< Kakshya::SoundFileContainer > m_audio_container
uint32_t m_refill_threshold
std::atomic< uint64_t > m_decode_head
@ FileIO
Filesystem I/O operations.
@ IO
Networking, file handling, streaming.
void add_region_group(std::unordered_map< std::string, RegionGroup > &groups, const RegionGroup &group)
Add a RegionGroup to a group map.
Tendency< D, float > threshold(const Tendency< D, float > &t, float thresh)
Zero output below threshold, pass through above.