memset(video_frame.data + frame_width * frame_height, 128, frame_width * frame_height); // Valid for both NV12 and planar.
}
- frame_callback(-1, AVRational{1, TIMEBASE}, -1, AVRational{1, TIMEBASE}, timecode++,
- video_frame, /*video_offset=*/0, video_format,
- FrameAllocator::Frame(), /*audio_offset=*/0, AudioFormat());
+ if (frame_callback != nullptr) {
+ frame_callback(-1, AVRational{1, TIMEBASE}, -1, AVRational{1, TIMEBASE}, timecode++,
+ video_frame, /*video_offset=*/0, video_format,
+ FrameAllocator::Frame(), /*audio_offset=*/0, AudioFormat());
+ }
last_frame_was_connected = false;
}
} else {
#ifdef HAVE_SRT
// SRT socket, already opened.
- AVInputFormat *mpegts_fmt = av_find_input_format("mpegts");
+ const AVInputFormat *mpegts_fmt = av_find_input_format("mpegts");
format_ctx = avformat_open_input_unique(&FFmpegCapture::read_srt_thunk, this,
mpegts_fmt, /*options=*/nullptr,
AVIOInterruptCB{ &FFmpegCapture::interrupt_cb_thunk, this });
// Open video decoder.
const AVCodecParameters *video_codecpar = format_ctx->streams[video_stream_index]->codecpar;
- AVCodec *video_codec = avcodec_find_decoder(video_codecpar->codec_id);
+ const AVCodec *video_codec = avcodec_find_decoder(video_codecpar->codec_id);
video_timebase = format_ctx->streams[video_stream_index]->time_base;
AVCodecContextWithDeleter video_codec_ctx = avcodec_alloc_context3_unique(nullptr);
fprintf(stderr, "%s: Cannot fill audio codec parameters\n", pathname.c_str());
return false;
}
- AVCodec *audio_codec = avcodec_find_decoder(audio_codecpar->codec_id);
+ const AVCodec *audio_codec = avcodec_find_decoder(audio_codecpar->codec_id);
if (audio_codec == nullptr) {
fprintf(stderr, "%s: Cannot find audio decoder\n", pathname.c_str());
return false;
// Main loop.
bool first_frame = true;
+ int consecutive_errors = 0;
while (!producer_thread_should_quit.should_quit()) {
if (process_queued_commands(format_ctx.get(), pathname, last_modified, /*rewound=*/nullptr)) {
return true;
AVFrameWithDeleter frame = decode_frame(format_ctx.get(), video_codec_ctx.get(), audio_codec_ctx.get(),
pathname, video_stream_index, audio_stream_index, subtitle_stream_index, audio_frame.get(), &audio_format, &audio_pts, &error);
if (error) {
- return false;
+ if (++consecutive_errors >= 100) {
+ fprintf(stderr, "More than 100 consecutive video frames, aborting playback.\n");
+ return false;
+ } else {
+ continue;
+ }
+ } else {
+ consecutive_errors = 0;
}
if (frame == nullptr) {
// EOF. Loop back to the start if we can.
1e3 * duration<double>(now - next_frame_start).count());
pts_origin = frame->pts;
start = next_frame_start = now;
- timecode += MAX_FPS * 2 + 1;
+ timecode += TYPICAL_FPS * 2 + 1;
}
}
bool finished_wakeup;
// Make sure to get the audio resampler reset. (This is a hack;
// ideally, the frame callback should just accept a way to signal
// audio discontinuity.)
- timecode += MAX_FPS * 2 + 1;
+ timecode += TYPICAL_FPS * 2 + 1;
}
last_neutral_color = get_neutral_color(frame->metadata);
- frame_callback(frame->pts, video_timebase, audio_pts, audio_timebase, timecode++,
- video_frame.get_and_release(), 0, video_format,
- audio_frame.get_and_release(), 0, audio_format);
+ if (frame_callback != nullptr) {
+ frame_callback(frame->pts, video_timebase, audio_pts, audio_timebase, timecode++,
+ video_frame.get_and_release(), 0, video_format,
+ audio_frame.get_and_release(), 0, audio_format);
+ }
first_frame = false;
last_frame = steady_clock::now();
last_frame_was_connected = true;
if (pkt.stream_index == audio_stream_index && audio_callback != nullptr) {
audio_callback(&pkt, format_ctx->streams[audio_stream_index]->time_base);
}
- if (pkt.stream_index == video_stream_index) {
+ if (pkt.stream_index == video_stream_index && video_callback != nullptr) {
+ video_callback(&pkt, format_ctx->streams[video_stream_index]->time_base);
+ }
+ if (pkt.stream_index == video_stream_index && global_flags.transcode_video) {
if (avcodec_send_packet(video_codec_ctx, &pkt) < 0) {
fprintf(stderr, "%s: Cannot send packet to video codec.\n", pathname.c_str());
*error = true;
return AVFrameWithDeleter(nullptr);
}
- } else if (pkt.stream_index == audio_stream_index) {
+ } else if (pkt.stream_index == audio_stream_index && global_flags.transcode_audio) {
has_audio = true;
if (avcodec_send_packet(audio_codec_ctx, &pkt) < 0) {
fprintf(stderr, "%s: Cannot send packet to audio codec.\n", pathname.c_str());
*error = true;
return AVFrameWithDeleter(nullptr);
}
+ sw_frame->pts = video_avframe->pts;
+ sw_frame->pkt_duration = video_avframe->pkt_duration;
video_avframe = move(sw_frame);
}
frame_finished = true;
if (height == 0) {
return frame->height;
} else {
- return width;
+ return height;
}
}