]> git.sesse.net Git - ffmpeg/blobdiff - avprobe.c
svq1: Check memory allocation
[ffmpeg] / avprobe.c
index 5ad56a182b224a2686cd3fb005365f536d8ea76b..a83fa6815dc983d7f8dc45231e4abe4f49f67a4d 100644 (file)
--- a/avprobe.c
+++ b/avprobe.c
@@ -24,6 +24,7 @@
 #include "libavformat/avformat.h"
 #include "libavcodec/avcodec.h"
 #include "libavutil/avstring.h"
+#include "libavutil/display.h"
 #include "libavutil/opt.h"
 #include "libavutil/pixdesc.h"
 #include "libavutil/dict.h"
@@ -60,7 +61,7 @@ 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 void exit_program(void)
+static void avprobe_cleanup(int ret)
 {
     av_dict_free(&fmt_entries_to_show);
 }
@@ -84,21 +85,21 @@ typedef enum {
     OBJECT
 } PrintElementType;
 
-typedef struct {
+typedef struct PrintElement {
     const char *name;
     PrintElementType type;
     int64_t index;
     int64_t nb_elems;
 } PrintElement;
 
-typedef struct {
+typedef struct PrintContext {
     PrintElement *prefix;
     int level;
     void (*print_header)(void);
     void (*print_footer)(void);
 
-    void (*print_array_header) (const char *name);
-    void (*print_array_footer) (const char *name);
+    void (*print_array_header) (const char *name, int plain_values);
+    void (*print_array_footer) (const char *name, int plain_values);
     void (*print_object_header)(const char *name);
     void (*print_object_footer)(const char *name);
 
@@ -157,9 +158,21 @@ static void ini_escape_print(const char *s)
     }
 }
 
-static void ini_print_array_header(const char *name)
+static void ini_print_array_header(const char *name, int plain_values)
 {
-    if (octx.prefix[octx.level -1].nb_elems)
+    if (!plain_values) {
+        /* Add a new line if we create a new full group */
+        if (octx.prefix[octx.level -1].nb_elems)
+            avio_printf(probe_out, "\n");
+    } else {
+        ini_escape_print(name);
+        avio_w8(probe_out, '=');
+    }
+}
+
+static void ini_print_array_footer(const char *name, int plain_values)
+{
+    if (plain_values)
         avio_printf(probe_out, "\n");
 }
 
@@ -181,15 +194,21 @@ static void ini_print_object_header(const char *name)
     }
 
     avio_printf(probe_out, "%s", name);
-    if (el && el->type == ARRAY)
+    if (el->type == ARRAY)
         avio_printf(probe_out, ".%"PRId64"", el->nb_elems);
     avio_printf(probe_out, "]\n");
 }
 
 static void ini_print_integer(const char *key, int64_t value)
 {
-    ini_escape_print(key);
-    avio_printf(probe_out, "=%"PRId64"\n", value);
+    if (key) {
+        ini_escape_print(key);
+        avio_printf(probe_out, "=%"PRId64"\n", value);
+    } else {
+        if (octx.prefix[octx.level -1].nb_elems)
+            avio_printf(probe_out, ",");
+        avio_printf(probe_out, "%"PRId64, value);
+    }
 }
 
 
@@ -214,7 +233,7 @@ static void json_print_footer(void)
     avio_printf(probe_out, "}\n");
 }
 
-static void json_print_array_header(const char *name)
+static void json_print_array_header(const char *name, int plain_values)
 {
     if (octx.prefix[octx.level -1].nb_elems)
         avio_printf(probe_out, ",\n");
@@ -223,7 +242,7 @@ static void json_print_array_header(const char *name)
     avio_printf(probe_out, "[\n");
 }
 
-static void json_print_array_footer(const char *name)
+static void json_print_array_footer(const char *name, int plain_values)
 {
     avio_printf(probe_out, "\n");
     AVP_INDENT();
@@ -249,10 +268,18 @@ static void json_print_object_footer(const char *name)
 
 static void json_print_integer(const char *key, int64_t value)
 {
-    if (octx.prefix[octx.level -1].nb_elems)
-        avio_printf(probe_out, ",\n");
-    AVP_INDENT();
-    avio_printf(probe_out, "\"%s\" : %"PRId64"", key, value);
+    if (key) {
+        if (octx.prefix[octx.level -1].nb_elems)
+            avio_printf(probe_out, ",\n");
+        AVP_INDENT();
+        avio_printf(probe_out, "\"%s\" : ", key);
+    } else {
+        if (octx.prefix[octx.level -1].nb_elems)
+            avio_printf(probe_out, ", ");
+        else
+            AVP_INDENT();
+    }
+    avio_printf(probe_out, "%"PRId64, value);
 }
 
 static void json_escape_print(const char *s)
@@ -302,6 +329,8 @@ static void old_print_object_header(const char *name)
         return;
 
     str = p = av_strdup(name);
+    if (!str)
+        return;
     while (*p) {
         *p = av_toupper(*p);
         p++;
@@ -319,6 +348,8 @@ static void old_print_object_footer(const char *name)
         return;
 
     str = p = av_strdup(name);
+    if (!str)
+        return;
     while (*p) {
         *p = av_toupper(*p);
         p++;
@@ -366,7 +397,7 @@ static void probe_group_enter(const char *name, int type)
 
     if (!octx.prefix || !name) {
         fprintf(stderr, "Out of memory\n");
-        exit(1);
+        exit_program(1);
     }
 
     if (octx.level) {
@@ -399,19 +430,19 @@ static void probe_footer(void)
 }
 
 
-static void probe_array_header(const char *name)
+static void probe_array_header(const char *name, int plain_values)
 {
     if (octx.print_array_header)
-        octx.print_array_header(name);
+        octx.print_array_header(name, plain_values);
 
     probe_group_enter(name, ARRAY);
 }
 
-static void probe_array_footer(const char *name)
+static void probe_array_footer(const char *name, int plain_values)
 {
     probe_group_leave();
     if (octx.print_array_footer)
-        octx.print_array_footer(name);
+        octx.print_array_footer(name, plain_values);
 }
 
 static void probe_object_header(const char *name)
@@ -557,10 +588,10 @@ static void show_packets(AVFormatContext *fmt_ctx)
     AVPacket pkt;
 
     av_init_packet(&pkt);
-    probe_array_header("packets");
+    probe_array_header("packets", 0);
     while (!av_read_frame(fmt_ctx, &pkt))
         show_packet(fmt_ctx, &pkt);
-    probe_array_footer("packets");
+    probe_array_footer("packets", 0);
 }
 
 static void show_stream(AVFormatContext *fmt_ctx, int stream_idx)
@@ -604,6 +635,8 @@ static void show_stream(AVFormatContext *fmt_ctx, int stream_idx)
         case AVMEDIA_TYPE_VIDEO:
             probe_int("width", dec_ctx->width);
             probe_int("height", dec_ctx->height);
+            probe_int("coded_width", dec_ctx->coded_width);
+            probe_int("coded_height", dec_ctx->coded_height);
             probe_int("has_b_frames", dec_ctx->has_b_frames);
             if (dec_ctx->sample_aspect_ratio.num)
                 sar = &dec_ctx->sample_aspect_ratio;
@@ -623,6 +656,12 @@ static void show_stream(AVFormatContext *fmt_ctx, int stream_idx)
             desc = av_pix_fmt_desc_get(dec_ctx->pix_fmt);
             probe_str("pix_fmt", desc ? desc->name : "unknown");
             probe_int("level", dec_ctx->level);
+
+            probe_str("color_range", av_color_range_name(dec_ctx->color_range));
+            probe_str("color_space", av_color_space_name(dec_ctx->colorspace));
+            probe_str("color_trc", av_color_transfer_name(dec_ctx->color_trc));
+            probe_str("color_pri", av_color_primaries_name(dec_ctx->color_primaries));
+            probe_str("chroma_loc", av_chroma_location_name(dec_ctx->chroma_sample_location));
             break;
 
         case AVMEDIA_TYPE_AUDIO:
@@ -662,6 +701,27 @@ static void show_stream(AVFormatContext *fmt_ctx, int stream_idx)
 
     probe_dict(stream->metadata, "tags");
 
+    if (stream->nb_side_data) {
+        int i, j;
+        probe_object_header("sidedata");
+        for (i = 0; i < stream->nb_side_data; i++) {
+            const AVPacketSideData* sd = &stream->side_data[i];
+            switch (sd->type) {
+            case AV_PKT_DATA_DISPLAYMATRIX:
+                probe_object_header("displaymatrix");
+                probe_array_header("matrix", 1);
+                for (j = 0; j < 9; j++)
+                    probe_int(NULL, ((int32_t *)sd->data)[j]);
+                probe_array_footer("matrix", 1);
+                probe_int("rotation",
+                          av_display_rotation_get((int32_t *)sd->data));
+                probe_object_footer("displaymatrix");
+                break;
+            }
+        }
+        probe_object_footer("sidedata");
+    }
+
     probe_object_footer("stream");
 }
 
@@ -767,10 +827,10 @@ static int probe_file(const char *filename)
         show_format(fmt_ctx);
 
     if (do_show_streams) {
-        probe_array_header("streams");
+        probe_array_header("streams", 0);
         for (i = 0; i < fmt_ctx->nb_streams; i++)
             show_stream(fmt_ctx, i);
-        probe_array_footer("streams");
+        probe_array_footer("streams", 0);
     }
 
     if (do_show_packets)
@@ -814,6 +874,7 @@ static int opt_output_format(void *optctx, const char *opt, const char *arg)
         octx.print_header        = ini_print_header;
         octx.print_footer        = ini_print_footer;
         octx.print_array_header  = ini_print_array_header;
+        octx.print_array_footer  = ini_print_array_footer;
         octx.print_object_header = ini_print_object_header;
 
         octx.print_integer = ini_print_integer;
@@ -854,7 +915,7 @@ static void opt_input_file(void *optctx, const char *arg)
         fprintf(stderr,
                 "Argument '%s' provided as input filename, but '%s' was already specified.\n",
                 arg, input_filename);
-        exit(1);
+        exit_program(1);
     }
     if (!strcmp(arg, "-"))
         arg = "pipe:";
@@ -919,7 +980,7 @@ int main(int argc, char **argv)
     if (!buffer)
         exit(1);
 
-    atexit(exit_program);
+    register_exit(avprobe_cleanup);
 
     options = real_options;
     parse_loglevel(argc, argv, options);
@@ -936,6 +997,7 @@ int main(int argc, char **argv)
     octx.print_footer = ini_print_footer;
 
     octx.print_array_header = ini_print_array_header;
+    octx.print_array_footer = ini_print_array_footer;
     octx.print_object_header = ini_print_object_header;
 
     octx.print_integer = ini_print_integer;
@@ -949,13 +1011,13 @@ int main(int argc, char **argv)
         fprintf(stderr,
                 "Use -h to get full help or, even better, run 'man %s'.\n",
                 program_name);
-        exit(1);
+        exit_program(1);
     }
 
     probe_out = avio_alloc_context(buffer, AVP_BUFFSIZE, 1, NULL, NULL,
                                  probe_buf_write, NULL);
     if (!probe_out)
-        exit(1);
+        exit_program(1);
 
     probe_header();
     ret = probe_file(input_filename);