#include <windows.h>
#include <psapi.h>
#endif
+#if HAVE_SETCONSOLECTRLHANDLER
+#include <windows.h>
+#endif
+
#if HAVE_SYS_SELECT_H
#include <sys/select.h>
static volatile int received_sigterm = 0;
static volatile int received_nb_signals = 0;
static volatile int transcode_init_done = 0;
+static volatile int ffmpeg_exited = 0;
static int main_return_code = 0;
static void
received_sigterm = sig;
received_nb_signals++;
term_exit_sigsafe();
- if(received_nb_signals > 3)
+ if(received_nb_signals > 3) {
+ write(2/*STDERR_FILENO*/, "Received > 3 system signals, hard exiting\n",
+ strlen("Received > 3 system signals, hard exiting\n"));
+
exit(123);
+ }
}
+#if HAVE_SETCONSOLECTRLHANDLER
+static BOOL WINAPI CtrlHandler(DWORD fdwCtrlType)
+{
+ av_log(NULL, AV_LOG_DEBUG, "\nReceived windows signal %ld\n", fdwCtrlType);
+
+ switch (fdwCtrlType)
+ {
+ case CTRL_C_EVENT:
+ case CTRL_BREAK_EVENT:
+ sigterm_handler(SIGINT);
+ return TRUE;
+
+ case CTRL_CLOSE_EVENT:
+ case CTRL_LOGOFF_EVENT:
+ case CTRL_SHUTDOWN_EVENT:
+ sigterm_handler(SIGTERM);
+ /* Basically, with these 3 events, when we return from this method the
+ process is hard terminated, so stall as long as we need to
+ to try and let the main thread(s) clean up and gracefully terminate
+ (we have at most 5 seconds, but should be done far before that). */
+ while (!ffmpeg_exited) {
+ Sleep(0);
+ }
+ return TRUE;
+
+ default:
+ av_log(NULL, AV_LOG_ERROR, "Received unknown windows signal %ld\n", fdwCtrlType);
+ return FALSE;
+ }
+}
+#endif
+
void term_init(void)
{
#if HAVE_TERMIOS_H
#ifdef SIGXCPU
signal(SIGXCPU, sigterm_handler);
#endif
+#if HAVE_SETCONSOLECTRLHANDLER
+ SetConsoleCtrlHandler((PHANDLER_ROUTINE) CtrlHandler, TRUE);
+#endif
}
/* read a key without blocking */
if (do_benchmark) {
int maxrss = getmaxrss() / 1024;
- printf("bench: maxrss=%ikB\n", maxrss);
+ av_log(NULL, AV_LOG_INFO, "bench: maxrss=%ikB\n", maxrss);
}
for (i = 0; i < nb_filtergraphs; i++) {
avformat_network_deinit();
if (received_sigterm) {
- av_log(NULL, AV_LOG_INFO, "Received signal %d: terminating.\n",
+ av_log(NULL, AV_LOG_INFO, "Exiting normally, received signal %d.\n",
(int) received_sigterm);
} else if (ret && transcode_init_done) {
av_log(NULL, AV_LOG_INFO, "Conversion failed!\n");
}
term_exit();
+ ffmpeg_exited = 1;
}
void remove_avoptions(AVDictionary **a, AVDictionary *b)
va_start(va, fmt);
vsnprintf(buf, sizeof(buf), fmt, va);
va_end(va);
- printf("bench: %8"PRIu64" %s \n", t - current_time, buf);
+ av_log(NULL, AV_LOG_INFO, "bench: %8"PRIu64" %s \n", t - current_time, buf);
}
current_time = t;
}
ret = AVERROR_INVALIDDATA;
}
- if (*got_output || ret<0 || pkt->size)
+ if (*got_output || ret<0)
decode_error_stat[ret<0] ++;
- if (!*got_output || ret < 0) {
- if (!pkt->size) {
- for (i = 0; i < ist->nb_filters; i++)
-#if 1
- av_buffersrc_add_ref(ist->filters[i]->filter, NULL, 0);
-#else
- av_buffersrc_add_frame(ist->filters[i]->filter, NULL);
-#endif
- }
+ if (ret < 0 && exit_on_error)
+ exit_program(1);
+
+ if (!*got_output || ret < 0)
return ret;
- }
ist->samples_decoded += decoded_frame->nb_samples;
ist->frames_decoded++;
);
}
- if (*got_output || ret<0 || pkt->size)
+ if (*got_output || ret<0)
decode_error_stat[ret<0] ++;
+ if (ret < 0 && exit_on_error)
+ exit_program(1);
+
if (*got_output && ret >= 0) {
if (ist->dec_ctx->width != decoded_frame->width ||
ist->dec_ctx->height != decoded_frame->height ||
}
}
- if (!*got_output || ret < 0) {
- if (!pkt->size) {
- for (i = 0; i < ist->nb_filters; i++)
-#if 1
- av_buffersrc_add_ref(ist->filters[i]->filter, NULL, 0);
-#else
- av_buffersrc_add_frame(ist->filters[i]->filter, NULL);
-#endif
- }
+ if (!*got_output || ret < 0)
return ret;
- }
if(ist->top_field_first>=0)
decoded_frame->top_field_first = ist->top_field_first;
int i, ret = avcodec_decode_subtitle2(ist->dec_ctx,
&subtitle, got_output, pkt);
- if (*got_output || ret<0 || pkt->size)
+ if (*got_output || ret<0)
decode_error_stat[ret<0] ++;
+ if (ret < 0 && exit_on_error)
+ exit_program(1);
+
if (ret < 0 || !*got_output) {
if (!pkt->size)
sub2video_flush(ist);
return ret;
}
+static int send_filter_eof(InputStream *ist)
+{
+ int i, ret;
+ for (i = 0; i < ist->nb_filters; i++) {
+#if 1
+ ret = av_buffersrc_add_ref(ist->filters[i]->filter, NULL, 0);
+#else
+ ret = av_buffersrc_add_frame(ist->filters[i]->filter, NULL);
+#endif
+ if (ret < 0)
+ return ret;
+ }
+ return 0;
+}
+
/* pkt = NULL means EOF (needed to flush decoder buffers) */
static int process_input_packet(InputStream *ist, const AVPacket *pkt)
{
return -1;
}
- if (ret < 0)
- return ret;
+ if (ret < 0) {
+ av_log(NULL, AV_LOG_ERROR, "Error while decoding stream #%d:%d: %s\n",
+ ist->file_index, ist->st->index, av_err2str(ret));
+ if (exit_on_error)
+ exit_program(1);
+ break;
+ }
avpkt.dts=
avpkt.pts= AV_NOPTS_VALUE;
break;
}
+ /* after flushing, send an EOF on all the filter inputs attached to the stream */
+ if (!pkt && ist->decoding_needed && !got_output) {
+ int ret = send_filter_eof(ist);
+ if (ret < 0) {
+ av_log(NULL, AV_LOG_FATAL, "Error marking filters as finished\n");
+ exit_program(1);
+ }
+ }
+
/* handle stream copy */
if (!ist->decoding_needed) {
ist->dts = ist->next_dts;
sub2video_heartbeat(ist, pkt.pts);
- ret = process_input_packet(ist, &pkt);
- if (ret < 0) {
- av_log(NULL, AV_LOG_ERROR, "Error while decoding stream #%d:%d: %s\n",
- ist->file_index, ist->st->index, av_err2str(ret));
- if (exit_on_error)
- exit_program(1);
- }
+ process_input_packet(ist, &pkt);
discard_packet:
av_free_packet(&pkt);
exit_program(1);
ti = getutime() - ti;
if (do_benchmark) {
- printf("bench: utime=%0.3fs\n", ti / 1000000.0);
+ av_log(NULL, AV_LOG_INFO, "bench: utime=%0.3fs\n", ti / 1000000.0);
}
av_log(NULL, AV_LOG_DEBUG, "%"PRIu64" frames successfully decoded, %"PRIu64" decoding errors\n",
decode_error_stat[0], decode_error_stat[1]);