Index: patched-ffmpeg-mt/ffmpeg.c |
=================================================================== |
--- patched-ffmpeg-mt/ffmpeg.c (revision 41250) |
+++ patched-ffmpeg-mt/ffmpeg.c (working copy) |
@@ -44,10 +44,15 @@ |
#if HAVE_SYS_RESOURCE_H |
#include <sys/types.h> |
+#include <sys/time.h> |
#include <sys/resource.h> |
#elif HAVE_GETPROCESSTIMES |
#include <windows.h> |
#endif |
+#if HAVE_GETPROCESSMEMORYINFO |
+#include <windows.h> |
+#include <psapi.h> |
+#endif |
#if HAVE_SYS_SELECT_H |
#include <sys/select.h> |
@@ -61,7 +66,6 @@ |
#elif HAVE_CONIO_H |
#include <conio.h> |
#endif |
-#undef time //needed because HAVE_AV_CONFIG_H is defined on top |
#include <time.h> |
#include "cmdutils.h" |
@@ -69,8 +73,6 @@ |
#undef NDEBUG |
#include <assert.h> |
-#undef exit |
- |
const char program_name[] = "FFmpeg"; |
const int program_birth_year = 2000; |
@@ -301,6 +303,7 @@ |
int64_t pts; /* current pts */ |
int is_start; /* is 1 at the start and after a discontinuity */ |
int showed_multi_packet_warning; |
+ int is_past_recording_time; |
} AVInputStream; |
typedef struct AVInputFile { |
@@ -1309,7 +1312,7 @@ |
ist->pts= ist->next_pts; |
if(avpkt.size && avpkt.size != pkt->size && |
- (!ist->showed_multi_packet_warning && verbose>0 || verbose>1)){ |
+ ((!ist->showed_multi_packet_warning && verbose>0) || verbose>1)){ |
fprintf(stderr, "Multiple frames in a packet from stream %d\n", pkt->stream_index); |
ist->showed_multi_packet_warning=1; |
} |
@@ -1502,7 +1505,10 @@ |
opkt.flags= pkt->flags; |
//FIXME remove the following 2 lines they shall be replaced by the bitstream filters |
- if(ost->st->codec->codec_id != CODEC_ID_H264) { |
+ if( ost->st->codec->codec_id != CODEC_ID_H264 |
+ && ost->st->codec->codec_id != CODEC_ID_MPEG1VIDEO |
+ && ost->st->codec->codec_id != CODEC_ID_MPEG2VIDEO |
+ ) { |
if(av_parser_change(ist->st->parser, ost->st->codec, &opkt.data, &opkt.size, data_buf, data_size, pkt->flags & PKT_FLAG_KEY)) |
opkt.destruct= av_destruct_packet; |
} else { |
@@ -1632,32 +1638,6 @@ |
fflush(stdout); |
} |
-static int stream_index_from_inputs(AVFormatContext **input_files, |
- int nb_input_files, |
- AVInputFile *file_table, |
- AVInputStream **ist_table, |
- enum CodecType type, |
- int programid) |
-{ |
- int p, q, z; |
- for(z=0; z<nb_input_files; z++) { |
- AVFormatContext *ic = input_files[z]; |
- for(p=0; p<ic->nb_programs; p++) { |
- AVProgram *program = ic->programs[p]; |
- if(program->id != programid) |
- continue; |
- for(q=0; q<program->nb_stream_indexes; q++) { |
- int sidx = program->stream_index[q]; |
- int ris = file_table[z].ist_index + sidx; |
- if(ist_table[ris]->discard && ic->streams[sidx]->codec->codec_type == type) |
- return ris; |
- } |
- } |
- } |
- |
- return -1; |
-} |
- |
/* |
* The following code is the main loop of the file converter |
*/ |
@@ -1789,33 +1769,42 @@ |
} |
} else { |
- if(opt_programid) { |
- found = 0; |
- j = stream_index_from_inputs(input_files, nb_input_files, file_table, ist_table, ost->st->codec->codec_type, opt_programid); |
- if(j != -1) { |
- ost->source_index = j; |
- found = 1; |
- } |
- } else { |
+ int best_nb_frames=-1; |
/* get corresponding input stream index : we select the first one with the right type */ |
found = 0; |
for(j=0;j<nb_istreams;j++) { |
+ int skip=0; |
ist = ist_table[j]; |
- if (ist->discard && |
+ if(opt_programid){ |
+ int pi,si; |
+ AVFormatContext *f= input_files[ ist->file_index ]; |
+ skip=1; |
+ for(pi=0; pi<f->nb_programs; pi++){ |
+ AVProgram *p= f->programs[pi]; |
+ if(p->id == opt_programid) |
+ for(si=0; si<p->nb_stream_indexes; si++){ |
+ if(f->streams[ p->stream_index[si] ] == ist->st) |
+ skip=0; |
+ } |
+ } |
+ } |
+ if (ist->discard && ist->st->discard != AVDISCARD_ALL && !skip && |
ist->st->codec->codec_type == ost->st->codec->codec_type) { |
- ost->source_index = j; |
- found = 1; |
- break; |
+ if(best_nb_frames < ist->st->codec_info_nb_frames){ |
+ best_nb_frames= ist->st->codec_info_nb_frames; |
+ ost->source_index = j; |
+ found = 1; |
+ } |
} |
} |
- } |
if (!found) { |
if(! opt_programid) { |
/* try again and reuse existing stream */ |
for(j=0;j<nb_istreams;j++) { |
ist = ist_table[j]; |
- if (ist->st->codec->codec_type == ost->st->codec->codec_type) { |
+ if ( ist->st->codec->codec_type == ost->st->codec->codec_type |
+ && ist->st->discard != AVDISCARD_ALL) { |
ost->source_index = j; |
found = 1; |
} |
@@ -1840,7 +1829,7 @@ |
/* for each output stream, we compute the right encoding parameters */ |
for(i=0;i<nb_ostreams;i++) { |
- AVMetadataTag *lang; |
+ AVMetadataTag *t = NULL, *lang = NULL; |
ost = ost_table[i]; |
os = output_files[ost->file_index]; |
ist = ist_table[ost->source_index]; |
@@ -1848,9 +1837,13 @@ |
codec = ost->st->codec; |
icodec = ist->st->codec; |
- if ((lang=av_metadata_get(ist->st->metadata, "language", NULL, 0)) |
- && !av_metadata_get(ost->st->metadata, "language", NULL, 0)) |
- av_metadata_set(&ost->st->metadata, "language", lang->value); |
+ if (av_metadata_get(ist->st->metadata, "language", NULL, 0)) |
+ lang = av_metadata_get(ost->st->metadata, "language", NULL, 0); |
+ while ((t = av_metadata_get(ist->st->metadata, "", t, AV_METADATA_IGNORE_SUFFIX))) { |
+ if (lang && !strcmp(t->key, "language")) |
+ continue; |
+ av_metadata_set2(&ost->st->metadata, t->key, t->value, 0); |
+ } |
ost->st->disposition = ist->st->disposition; |
codec->bits_per_raw_sample= icodec->bits_per_raw_sample; |
@@ -2093,25 +2086,14 @@ |
/* init pts */ |
for(i=0;i<nb_istreams;i++) { |
+ AVStream *st; |
ist = ist_table[i]; |
- ist->pts = 0; |
+ st= ist->st; |
+ ist->pts = st->avg_frame_rate.num ? - st->codec->has_b_frames*AV_TIME_BASE / av_q2d(st->avg_frame_rate) : 0; |
ist->next_pts = AV_NOPTS_VALUE; |
ist->is_start = 1; |
} |
- /* set the duration of the output to the duration of the input |
- * if the output ends up being different, it'll be corrected later */ |
- for (i=0;i<nb_output_files;i++) { |
- AVFormatContext *out_file = output_files[i]; |
- AVFormatContext *in_file = input_files[i]; |
- |
- if (recording_time != INT64_MAX) { |
- out_file->duration = recording_time / 1000000 * AV_TIME_BASE; |
- } else { |
- out_file->duration = in_file->duration; |
- } |
- } |
- |
/* set meta data information from input file if required */ |
for (i=0;i<nb_meta_data_maps;i++) { |
AVFormatContext *out_file; |
@@ -2226,11 +2208,8 @@ |
ost = ost_table[i]; |
os = output_files[ost->file_index]; |
ist = ist_table[ost->source_index]; |
- if(no_packet[ist->file_index]) |
+ if(ist->is_past_recording_time || no_packet[ist->file_index]) |
continue; |
- if(ost->st->codec->codec_type == CODEC_TYPE_VIDEO) |
- opts = ost->sync_opts * av_q2d(ost->st->codec->time_base); |
- else |
opts = ost->st->pts.val * av_q2d(ost->st->time_base); |
ipts = (double)ist->pts; |
if (!file_table[ist->file_index].eof_reached){ |
@@ -2259,10 +2238,6 @@ |
break; |
} |
- /* finish if recording time exhausted */ |
- if (opts_min >= (recording_time / 1000000.0)) |
- break; |
- |
/* finish if limit size exhausted */ |
if (limit_filesize != 0 && limit_filesize < url_ftell(output_files[0]->pb)) |
break; |
@@ -2326,8 +2301,11 @@ |
} |
/* finish if recording time exhausted */ |
- if (pkt.pts * av_q2d(ist->st->time_base) >= (recording_time / 1000000.0)) |
+ if (recording_time != INT64_MAX && |
+ av_compare_ts(pkt.pts, ist->st->time_base, recording_time + start_time, (AVRational){1, 1000000}) >= 0) { |
+ ist->is_past_recording_time = 1; |
goto discard_packet; |
+ } |
//fprintf(stderr,"read #%d.%d size=%d\n", ist->file_index, ist->index, pkt.size); |
if (output_packet(ist, ist_index, ost_table, nb_ostreams, &pkt) < 0) { |
@@ -2600,7 +2578,7 @@ |
av_exit(1); |
} |
} else { |
- list_fmts(avcodec_pix_fmt_string, PIX_FMT_NB); |
+ show_pix_fmts(); |
av_exit(0); |
} |
} |
@@ -2866,7 +2844,10 @@ |
int64_t timestamp; |
if (last_asked_format) { |
- file_iformat = av_find_input_format(last_asked_format); |
+ if (!(file_iformat = av_find_input_format(last_asked_format))) { |
+ fprintf(stderr, "Unknown input format: '%s'\n", last_asked_format); |
+ av_exit(1); |
+ } |
last_asked_format = NULL; |
} |
@@ -2913,10 +2894,27 @@ |
av_exit(1); |
} |
if(opt_programid) { |
- int i; |
- for(i=0; i<ic->nb_programs; i++) |
- if(ic->programs[i]->id != opt_programid) |
- ic->programs[i]->discard = AVDISCARD_ALL; |
+ int i, j; |
+ int found=0; |
+ for(i=0; i<ic->nb_streams; i++){ |
+ ic->streams[i]->discard= AVDISCARD_ALL; |
+ } |
+ for(i=0; i<ic->nb_programs; i++){ |
+ AVProgram *p= ic->programs[i]; |
+ if(p->id != opt_programid){ |
+ p->discard = AVDISCARD_ALL; |
+ }else{ |
+ found=1; |
+ for(j=0; j<p->nb_stream_indexes; j++){ |
+ ic->streams[p->stream_index[j]]->discard= 0; |
+ } |
+ } |
+ } |
+ if(!found){ |
+ fprintf(stderr, "Specified program id not found\n"); |
+ av_exit(1); |
+ } |
+ opt_programid=0; |
} |
ic->loop_input = loop_input; |
@@ -3210,6 +3208,7 @@ |
video_disable = 0; |
av_freep(&video_codec_name); |
video_stream_copy = 0; |
+ frame_pix_fmt = PIX_FMT_NONE; |
} |
static void new_audio_stream(AVFormatContext *oc) |
@@ -3544,6 +3543,24 @@ |
#endif |
} |
+static int64_t getmaxrss(void) |
+{ |
+#if HAVE_GETRUSAGE && HAVE_STRUCT_RUSAGE_RU_MAXRSS |
+ struct rusage rusage; |
+ getrusage(RUSAGE_SELF, &rusage); |
+ return (int64_t)rusage.ru_maxrss * 1024; |
+#elif HAVE_GETPROCESSMEMORYINFO |
+ HANDLE proc; |
+ PROCESS_MEMORY_COUNTERS memcounters; |
+ proc = GetCurrentProcess(); |
+ memcounters.cb = sizeof(memcounters); |
+ GetProcessMemoryInfo(proc, &memcounters, sizeof(memcounters)); |
+ return memcounters.PeakPagefileUsage; |
+#else |
+ return 0; |
+#endif |
+} |
+ |
static void parse_matrix_coeffs(uint16_t *dest, const char *str) |
{ |
int i; |
@@ -4038,7 +4055,8 @@ |
av_exit(1); |
ti = getutime() - ti; |
if (do_benchmark) { |
- printf("bench: utime=%0.3fs\n", ti / 1000000.0); |
+ int maxrss = getmaxrss() / 1024; |
+ printf("bench: utime=%0.3fs maxrss=%ikB\n", ti / 1000000.0, maxrss); |
} |
return av_exit(0); |