X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=ffmpeg.c;h=e592629d0ea9ec228a0080d5d955f0c84b4b5472;hb=6e5864ab294c45814e6d417546f885a0c7dfb7cc;hp=f537ce9c5d4807fd3ebd6f1b10bb41114939e042;hpb=87961eff23abf710b575488ac62ee7d121a4ea07;p=ffmpeg diff --git a/ffmpeg.c b/ffmpeg.c index f537ce9c5d4..e592629d0ea 100644 --- a/ffmpeg.c +++ b/ffmpeg.c @@ -79,6 +79,10 @@ #include #include #endif +#if HAVE_SETCONSOLECTRLHANDLER +#include +#endif + #if HAVE_SYS_SELECT_H #include @@ -313,6 +317,7 @@ void term_exit(void) 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 @@ -322,12 +327,45 @@ sigterm_handler(int sig) received_nb_signals++; term_exit_sigsafe(); if(received_nb_signals > 3) { - write(STDERR_FILENO, "Received > 3 system signals, hard exiting\n", - strlen("Received > 3 system signals, hard exiting\n")); + 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 @@ -361,6 +399,9 @@ void term_init(void) #ifdef SIGXCPU signal(SIGXCPU, sigterm_handler); #endif +#if HAVE_SETCONSOLECTRLHANDLER + SetConsoleCtrlHandler((PHANDLER_ROUTINE) CtrlHandler, TRUE); +#endif } /* read a key without blocking */ @@ -536,6 +577,7 @@ static void ffmpeg_cleanup(int ret) av_log(NULL, AV_LOG_INFO, "Conversion failed!\n"); } term_exit(); + ffmpeg_exited = 1; } void remove_avoptions(AVDictionary **a, AVDictionary *b) @@ -1869,20 +1911,14 @@ static int decode_audio(InputStream *ist, AVPacket *pkt, int *got_output) 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++; @@ -2014,9 +2050,12 @@ static int decode_video(InputStream *ist, AVPacket *pkt, int *got_output) ); } - 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 || @@ -2031,17 +2070,8 @@ static int decode_video(InputStream *ist, AVPacket *pkt, int *got_output) } } - 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; @@ -2132,9 +2162,12 @@ static int transcode_subtitles(InputStream *ist, AVPacket *pkt, int *got_output) 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); @@ -2186,6 +2219,21 @@ out: 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) { @@ -2270,8 +2318,13 @@ 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; @@ -2290,6 +2343,15 @@ static int process_input_packet(InputStream *ist, const AVPacket *pkt) 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; @@ -3765,13 +3827,7 @@ static int process_input(int file_index) 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);