]> git.sesse.net Git - ffmpeg/blobdiff - ffprobe.c
Merge commit '66a1ccd7467ab1913cd8877114c6d4c2588bb12f'
[ffmpeg] / ffprobe.c
index 9e5cd04101c02216f21ac592a43381512c758043..1cf6c42a11ba0734c2e2443582c98d95bac5ea91 100644 (file)
--- a/ffprobe.c
+++ b/ffprobe.c
@@ -69,6 +69,7 @@ static int use_value_sexagesimal_format = 0;
 static int show_private_data            = 1;
 
 static char *print_format;
+static char *stream_specifier;
 
 /* section structure definition */
 
@@ -138,13 +139,14 @@ static const char unit_second_str[]         = "s"    ;
 static const char unit_hertz_str[]          = "Hz"   ;
 static const char unit_byte_str[]           = "byte" ;
 static const char unit_bit_per_second_str[] = "bit/s";
+
 static uint64_t *nb_streams_packets;
 static uint64_t *nb_streams_frames;
+static int *selected_streams;
 
-void av_noreturn exit_program(int ret)
+static void exit_program(void)
 {
     av_dict_free(&fmt_entries_to_show);
-    exit(ret);
 }
 
 struct unit_value {
@@ -1615,14 +1617,16 @@ static void read_packets(WriterContext *w, AVFormatContext *fmt_ctx)
     av_init_packet(&pkt);
 
     while (!av_read_frame(fmt_ctx, &pkt)) {
-        if (do_read_packets) {
-            if (do_show_packets)
-                show_packet(w, fmt_ctx, &pkt, i++);
-            nb_streams_packets[pkt.stream_index]++;
-        }
-        if (do_read_frames) {
-            pkt1 = pkt;
-            while (pkt1.size && process_frame(w, fmt_ctx, &frame, &pkt1) > 0);
+        if (selected_streams[pkt.stream_index]) {
+            if (do_read_packets) {
+                if (do_show_packets)
+                    show_packet(w, fmt_ctx, &pkt, i++);
+                nb_streams_packets[pkt.stream_index]++;
+            }
+            if (do_read_frames) {
+                pkt1 = pkt;
+                while (pkt1.size && process_frame(w, fmt_ctx, &frame, &pkt1) > 0);
+            }
         }
         av_free_packet(&pkt);
     }
@@ -1790,7 +1794,8 @@ static void show_streams(WriterContext *w, AVFormatContext *fmt_ctx)
     int i;
     writer_print_section_header(w, SECTION_ID_STREAMS);
     for (i = 0; i < fmt_ctx->nb_streams; i++)
-        show_stream(w, fmt_ctx, i);
+        if (selected_streams[i])
+            show_stream(w, fmt_ctx, i);
     writer_print_section_footer(w);
 }
 
@@ -1897,7 +1902,7 @@ static void close_input_file(AVFormatContext **ctx_ptr)
 static int probe_file(WriterContext *wctx, const char *filename)
 {
     AVFormatContext *fmt_ctx;
-    int ret;
+    int ret, i;
     int section_id;
 
     do_read_frames = do_show_frames || do_count_frames;
@@ -1907,6 +1912,22 @@ static int probe_file(WriterContext *wctx, const char *filename)
     if (ret >= 0) {
         nb_streams_frames  = av_calloc(fmt_ctx->nb_streams, sizeof(*nb_streams_frames));
         nb_streams_packets = av_calloc(fmt_ctx->nb_streams, sizeof(*nb_streams_packets));
+        selected_streams   = av_calloc(fmt_ctx->nb_streams, sizeof(*selected_streams));
+
+        for (i = 0; i < fmt_ctx->nb_streams; i++) {
+            if (stream_specifier) {
+                ret = avformat_match_stream_specifier(fmt_ctx,
+                                                      fmt_ctx->streams[i],
+                                                      stream_specifier);
+                if (ret < 0)
+                    goto end;
+                else
+                    selected_streams[i] = ret;
+            } else {
+                selected_streams[i] = 1;
+            }
+        }
+
         if (do_read_frames || do_read_packets) {
             if (do_show_frames && do_show_packets &&
                 wctx->writer->flags & WRITER_FLAG_PUT_PACKETS_AND_FRAMES_IN_SAME_CHAPTER)
@@ -1926,9 +1947,11 @@ static int probe_file(WriterContext *wctx, const char *filename)
         if (do_show_format)
             show_format(wctx, fmt_ctx);
 
+    end:
         close_input_file(&fmt_ctx);
         av_freep(&nb_streams_frames);
         av_freep(&nb_streams_packets);
+        av_freep(&selected_streams);
     }
     return ret;
 }
@@ -2063,6 +2086,7 @@ static const OptionDef real_options[] = {
     { "print_format", OPT_STRING | HAS_ARG, {(void*)&print_format},
       "set the output printing format (available formats are: default, compact, csv, flat, ini, json, xml)", "format" },
     { "of", OPT_STRING | HAS_ARG, {(void*)&print_format}, "alias for -print_format", "format" },
+    { "select_streams", OPT_STRING | HAS_ARG, {(void*)&stream_specifier}, "select the specified streams", "stream_specifier" },
     { "show_data",    OPT_BOOL, {(void*)&do_show_data}, "show packets data" },
     { "show_error",   OPT_BOOL, {(void*)&do_show_error} ,  "show probing error" },
     { "show_format",  OPT_BOOL, {&do_show_format} , "show format/container info" },
@@ -2093,6 +2117,8 @@ int main(int argc, char **argv)
     int ret;
 
     av_log_set_flags(AV_LOG_SKIP_REPEATED);
+    atexit(exit_program);
+
     options = real_options;
     parse_loglevel(argc, argv, options);
     av_register_all();
@@ -2117,6 +2143,10 @@ int main(int argc, char **argv)
 
     if (!print_format)
         print_format = av_strdup("default");
+    if (!print_format) {
+        ret = AVERROR(ENOMEM);
+        goto end;
+    }
     w_name = av_strtok(print_format, "=", &buf);
     w_args = buf;