331{
332 static std::once_flag logger_once;
334
335 if (avformat_network_init() < 0)
336 return 2;
337
338 AVFormatContext *format_context = avformat_alloc_context();
339 if (!format_context) {
340 avformat_network_deinit();
341 return 2;
342 }
343
345 format_context->flags |= AVFMT_FLAG_NOBUFFER;
346 format_context->max_delay = 0;
348
349 auto finish = [&](int error) {
351 avformat_close_input(&format_context);
352 avformat_network_deinit();
355 return error;
356 };
357
358 const std::string uri = url->BuildURI().ToUTF8().data();
359 const wxString scheme = url->GetScheme();
360 const bool http_stream = scheme.CmpNoCase("http") == 0 || scheme.CmpNoCase("https") == 0;
361 AVDictionary *options = nullptr;
362 if (http_stream) {
363
364
365
366
367
368
369
370
371
372
373
374 av_dict_set(&options, "fflags", "nobuffer", 0);
375 av_dict_set(&options, "probesize", "5000000", 0);
376 av_dict_set(&options, "analyzeduration", "1000000", 0);
377 av_dict_set(&options, "rw_timeout", "5000000", 0);
378 av_dict_set(&options, "timeout", "5000000", 0);
379 } else {
380 av_dict_set(&options, "rtsp_transport", "tcp", 0);
381 }
383 int error = avformat_open_input(&format_context, uri.c_str(), nullptr, &options);
384 av_dict_free(&options);
386 if (error < 0)
387 return finish(2);
388
390 error = avformat_find_stream_info(format_context, nullptr);
392 if (error < 0)
393 return finish(2);
394
395 const int video_stream = av_find_best_stream(format_context, AVMEDIA_TYPE_VIDEO, -1, -1, nullptr, 0);
396 if (video_stream < 0)
397 return finish(2);
398
399 AVVideoDecoder decoder;
400 if (decoder.
open(*format_context->streams[video_stream]->codecpar) < 0)
401 return finish(2);
402
403
404
405
406
407 auto apply_video_size = [&](wxSize size) {
408 if (!size.IsFullySpecified() || size.x <= 0 || size.y <= 0)
409 return false;
413 return true;
414 };
415 bool have_size = apply_video_size({format_context->streams[video_stream]->codecpar->width,
416 format_context->streams[video_stream]->codecpar->height});
417 int size_probe_frames = 0;
418
419 AVPacket *packet = av_packet_alloc();
420 if (!packet)
421 return finish(2);
422
423 while (
m_url == url) {
425 error = av_read_frame(format_context, packet);
428 break;
429 if (error < 0)
430 break;
431 if (packet->stream_index == video_stream) {
432 const int decode_error = decoder.
decode(*packet);
433 if (decode_error == 0) {
434 if (!have_size) {
436 if (!have_size) {
437 av_packet_unref(packet);
438
439
440
441 if (++size_probe_frames > 120)
442 break;
443 continue;
444 }
445 }
448#ifdef _WIN32
449 wxBitmap frame;
451#else
452 wxImage frame;
454#endif
457 break;
458 if (frame.IsOk())
461 CallAfter([this] {
463 Refresh();
464 });
465 }
466 }
467 }
468 av_packet_unref(packet);
469 }
470
471 av_packet_free(&packet);
472 return finish(
m_url == url ? 2 : 1);
473}
bool toWxBitmap(wxBitmap &bitmap, wxSize const &size)
Definition AVVideoDecoder.cpp:164
wxSize decoded_frame_size() const
Definition AVVideoDecoder.hpp:46
int decode(Bambu_Sample const &sample)
Definition AVVideoDecoder.cpp:75
bool toWxImage(wxImage &image, wxSize const &size)
Definition AVVideoDecoder.cpp:120
int open(Bambu_StreamInfo const &info)
Definition AVVideoDecoder.cpp:34