From fb02ac20dbdb3ecfc770f8f886daa83511568270 Mon Sep 17 00:00:00 2001
From: Stefano Sabatini <stefasab@gmail.com>
Date: Wed, 2 Oct 2013 16:55:15 +0200
Subject: [PATCH] ffprobe: check for errors, and abort immediately
This allows to make use of validation features.
---
ffprobe.c | 122 ++++++++++++++++++++++++++++++++++++++++++--------------------
1 file changed, 84 insertions(+), 38 deletions(-)
diff --git a/ffprobe.c b/ffprobe.c
index 80a286b..581bce9 100644
|
a
|
b
|
static inline void writer_print_integer(WriterContext *wctx,
|
| 428 | 428 | } |
| 429 | 429 | } |
| 430 | 430 | |
| 431 | | static inline void writer_print_string(WriterContext *wctx, |
| 432 | | const char *key, const char *val, int opt) |
| | 431 | static inline int writer_print_string(WriterContext *wctx, |
| | 432 | const char *key, const char *val, int opt) |
| 433 | 433 | { |
| 434 | 434 | const struct section *section = wctx->section[wctx->level]; |
| | 435 | int ret = 0; |
| 435 | 436 | |
| 436 | 437 | if (opt && !(wctx->writer->flags & WRITER_FLAG_DISPLAY_OPTIONAL_FIELDS)) |
| 437 | | return; |
| | 438 | return 0; |
| 438 | 439 | |
| 439 | 440 | if (section->show_all_entries || av_dict_get(section->entries_to_show, key, NULL, 0)) { |
| 440 | 441 | wctx->writer->print_string(wctx, key, val); |
| 441 | 442 | wctx->nb_item[wctx->level]++; |
| 442 | 443 | } |
| | 444 | |
| | 445 | return ret; |
| 443 | 446 | } |
| 444 | 447 | |
| 445 | 448 | static inline void writer_print_rational(WriterContext *wctx, |
| … |
… |
static void writer_register_all(void)
|
| 1455 | 1458 | #define print_section_header(s) writer_print_section_header(w, s) |
| 1456 | 1459 | #define print_section_footer(s) writer_print_section_footer(w, s) |
| 1457 | 1460 | |
| 1458 | | static inline void show_tags(WriterContext *wctx, AVDictionary *tags, int section_id) |
| | 1461 | static inline int show_tags(WriterContext *wctx, AVDictionary *tags, int section_id) |
| 1459 | 1462 | { |
| 1460 | 1463 | AVDictionaryEntry *tag = NULL; |
| | 1464 | int ret = 0; |
| 1461 | 1465 | |
| 1462 | 1466 | if (!tags) |
| 1463 | | return; |
| | 1467 | return 0; |
| 1464 | 1468 | writer_print_section_header(wctx, section_id); |
| 1465 | | while ((tag = av_dict_get(tags, "", tag, AV_DICT_IGNORE_SUFFIX))) |
| 1466 | | writer_print_string(wctx, tag->key, tag->value, 0); |
| | 1469 | |
| | 1470 | while ((tag = av_dict_get(tags, "", tag, AV_DICT_IGNORE_SUFFIX))) { |
| | 1471 | ret = writer_print_string(wctx, tag->key, tag->value, 0); |
| | 1472 | if (ret < 0) |
| | 1473 | break; |
| | 1474 | } |
| 1467 | 1475 | writer_print_section_footer(wctx); |
| | 1476 | |
| | 1477 | return ret; |
| 1468 | 1478 | } |
| 1469 | 1479 | |
| 1470 | 1480 | static void show_packet(WriterContext *w, AVFormatContext *fmt_ctx, AVPacket *pkt, int packet_idx) |
| … |
… |
end:
|
| 1723 | 1733 | return ret; |
| 1724 | 1734 | } |
| 1725 | 1735 | |
| 1726 | | static void read_packets(WriterContext *w, AVFormatContext *fmt_ctx) |
| | 1736 | static int read_packets(WriterContext *w, AVFormatContext *fmt_ctx) |
| 1727 | 1737 | { |
| 1728 | 1738 | int i, ret = 0; |
| 1729 | 1739 | int64_t cur_ts = fmt_ctx->start_time; |
| … |
… |
static void read_packets(WriterContext *w, AVFormatContext *fmt_ctx)
|
| 1738 | 1748 | break; |
| 1739 | 1749 | } |
| 1740 | 1750 | } |
| | 1751 | |
| | 1752 | return ret; |
| 1741 | 1753 | } |
| 1742 | 1754 | |
| 1743 | | static void show_stream(WriterContext *w, AVFormatContext *fmt_ctx, int stream_idx, int in_program) |
| | 1755 | static int show_stream(WriterContext *w, AVFormatContext *fmt_ctx, int stream_idx, int in_program) |
| 1744 | 1756 | { |
| 1745 | 1757 | AVStream *stream = fmt_ctx->streams[stream_idx]; |
| 1746 | 1758 | AVCodecContext *dec_ctx; |
| … |
… |
static void show_stream(WriterContext *w, AVFormatContext *fmt_ctx, int stream_i
|
| 1749 | 1761 | const char *s; |
| 1750 | 1762 | AVRational sar, dar; |
| 1751 | 1763 | AVBPrint pbuf; |
| | 1764 | int ret = 0; |
| 1752 | 1765 | |
| 1753 | 1766 | av_bprint_init(&pbuf, 1, AV_BPRINT_SIZE_UNLIMITED); |
| 1754 | 1767 | |
| … |
… |
static void show_stream(WriterContext *w, AVFormatContext *fmt_ctx, int stream_i
|
| 1903 | 1916 | writer_print_section_footer(w); |
| 1904 | 1917 | } |
| 1905 | 1918 | |
| 1906 | | show_tags(w, stream->metadata, in_program ? SECTION_ID_PROGRAM_STREAM_TAGS : SECTION_ID_STREAM_TAGS); |
| | 1919 | ret = show_tags(w, stream->metadata, in_program ? SECTION_ID_PROGRAM_STREAM_TAGS : SECTION_ID_STREAM_TAGS); |
| 1907 | 1920 | |
| 1908 | 1921 | writer_print_section_footer(w); |
| 1909 | 1922 | av_bprint_finalize(&pbuf, NULL); |
| 1910 | 1923 | fflush(stdout); |
| | 1924 | |
| | 1925 | return ret; |
| 1911 | 1926 | } |
| 1912 | 1927 | |
| 1913 | | static void show_streams(WriterContext *w, AVFormatContext *fmt_ctx) |
| | 1928 | static int show_streams(WriterContext *w, AVFormatContext *fmt_ctx) |
| 1914 | 1929 | { |
| 1915 | | int i; |
| | 1930 | int i, ret = 0; |
| | 1931 | |
| 1916 | 1932 | writer_print_section_header(w, SECTION_ID_STREAMS); |
| 1917 | 1933 | for (i = 0; i < fmt_ctx->nb_streams; i++) |
| 1918 | | if (selected_streams[i]) |
| 1919 | | show_stream(w, fmt_ctx, i, 0); |
| | 1934 | if (selected_streams[i]) { |
| | 1935 | ret = show_stream(w, fmt_ctx, i, 0); |
| | 1936 | if (ret < 0) |
| | 1937 | break; |
| | 1938 | } |
| 1920 | 1939 | writer_print_section_footer(w); |
| | 1940 | |
| | 1941 | return ret; |
| 1921 | 1942 | } |
| 1922 | 1943 | |
| 1923 | | static void show_program(WriterContext *w, AVFormatContext *fmt_ctx, AVProgram *program) |
| | 1944 | static int show_program(WriterContext *w, AVFormatContext *fmt_ctx, AVProgram *program) |
| 1924 | 1945 | { |
| 1925 | | int i; |
| | 1946 | int i, ret = 0; |
| 1926 | 1947 | |
| 1927 | 1948 | writer_print_section_header(w, SECTION_ID_PROGRAM); |
| 1928 | 1949 | print_int("program_id", program->id); |
| … |
… |
static void show_program(WriterContext *w, AVFormatContext *fmt_ctx, AVProgram *
|
| 1934 | 1955 | print_time("start_time", program->start_time, &AV_TIME_BASE_Q); |
| 1935 | 1956 | print_ts("end_pts", program->end_time); |
| 1936 | 1957 | print_time("end_time", program->end_time, &AV_TIME_BASE_Q); |
| 1937 | | show_tags(w, program->metadata, SECTION_ID_PROGRAM_TAGS); |
| | 1958 | ret = show_tags(w, program->metadata, SECTION_ID_PROGRAM_TAGS); |
| | 1959 | if (ret < 0) |
| | 1960 | goto end; |
| 1938 | 1961 | |
| 1939 | 1962 | writer_print_section_header(w, SECTION_ID_PROGRAM_STREAMS); |
| 1940 | 1963 | for (i = 0; i < program->nb_stream_indexes; i++) { |
| 1941 | | if (selected_streams[program->stream_index[i]]) |
| 1942 | | show_stream(w, fmt_ctx, program->stream_index[i], 1); |
| | 1964 | if (selected_streams[program->stream_index[i]]) { |
| | 1965 | ret = show_stream(w, fmt_ctx, program->stream_index[i], 1); |
| | 1966 | if (ret < 0) |
| | 1967 | break; |
| | 1968 | } |
| 1943 | 1969 | } |
| 1944 | 1970 | writer_print_section_footer(w); |
| 1945 | 1971 | |
| | 1972 | end: |
| 1946 | 1973 | writer_print_section_footer(w); |
| | 1974 | return ret; |
| 1947 | 1975 | } |
| 1948 | 1976 | |
| 1949 | | static void show_programs(WriterContext *w, AVFormatContext *fmt_ctx) |
| | 1977 | static int show_programs(WriterContext *w, AVFormatContext *fmt_ctx) |
| 1950 | 1978 | { |
| 1951 | | int i; |
| | 1979 | int i, ret = 0; |
| 1952 | 1980 | |
| 1953 | 1981 | writer_print_section_header(w, SECTION_ID_PROGRAMS); |
| 1954 | 1982 | for (i = 0; i < fmt_ctx->nb_programs; i++) { |
| 1955 | 1983 | AVProgram *program = fmt_ctx->programs[i]; |
| 1956 | 1984 | if (!program) |
| 1957 | 1985 | continue; |
| 1958 | | show_program(w, fmt_ctx, program); |
| | 1986 | ret = show_program(w, fmt_ctx, program); |
| | 1987 | if (ret < 0) |
| | 1988 | break; |
| 1959 | 1989 | } |
| 1960 | 1990 | writer_print_section_footer(w); |
| | 1991 | return ret; |
| 1961 | 1992 | } |
| 1962 | 1993 | |
| 1963 | | static void show_chapters(WriterContext *w, AVFormatContext *fmt_ctx) |
| | 1994 | static int show_chapters(WriterContext *w, AVFormatContext *fmt_ctx) |
| 1964 | 1995 | { |
| 1965 | | int i; |
| | 1996 | int i, ret = 0; |
| 1966 | 1997 | |
| 1967 | 1998 | writer_print_section_header(w, SECTION_ID_CHAPTERS); |
| 1968 | 1999 | for (i = 0; i < fmt_ctx->nb_chapters; i++) { |
| … |
… |
static void show_chapters(WriterContext *w, AVFormatContext *fmt_ctx)
|
| 1975 | 2006 | print_time("start_time", chapter->start, &chapter->time_base); |
| 1976 | 2007 | print_int("end", chapter->end); |
| 1977 | 2008 | print_time("end_time", chapter->end, &chapter->time_base); |
| 1978 | | show_tags(w, chapter->metadata, SECTION_ID_CHAPTER_TAGS); |
| | 2009 | ret = show_tags(w, chapter->metadata, SECTION_ID_CHAPTER_TAGS); |
| 1979 | 2010 | writer_print_section_footer(w); |
| 1980 | 2011 | } |
| 1981 | 2012 | writer_print_section_footer(w); |
| | 2013 | |
| | 2014 | return ret; |
| 1982 | 2015 | } |
| 1983 | 2016 | |
| 1984 | | static void show_format(WriterContext *w, AVFormatContext *fmt_ctx) |
| | 2017 | static int show_format(WriterContext *w, AVFormatContext *fmt_ctx) |
| 1985 | 2018 | { |
| 1986 | 2019 | char val_str[128]; |
| 1987 | 2020 | int64_t size = fmt_ctx->pb ? avio_size(fmt_ctx->pb) : -1; |
| | 2021 | int ret = 0; |
| 1988 | 2022 | |
| 1989 | 2023 | writer_print_section_header(w, SECTION_ID_FORMAT); |
| 1990 | 2024 | print_str("filename", fmt_ctx->filename); |
| … |
… |
static void show_format(WriterContext *w, AVFormatContext *fmt_ctx)
|
| 2002 | 2036 | if (fmt_ctx->bit_rate > 0) print_val ("bit_rate", fmt_ctx->bit_rate, unit_bit_per_second_str); |
| 2003 | 2037 | else print_str_opt("bit_rate", "N/A"); |
| 2004 | 2038 | print_int("probe_score", av_format_get_probe_score(fmt_ctx)); |
| 2005 | | show_tags(w, fmt_ctx->metadata, SECTION_ID_FORMAT_TAGS); |
| | 2039 | ret = show_tags(w, fmt_ctx->metadata, SECTION_ID_FORMAT_TAGS); |
| 2006 | 2040 | |
| 2007 | 2041 | writer_print_section_footer(w); |
| 2008 | 2042 | fflush(stdout); |
| | 2043 | return ret; |
| 2009 | 2044 | } |
| 2010 | 2045 | |
| 2011 | 2046 | static void show_error(WriterContext *w, int err) |
| … |
… |
static int probe_file(WriterContext *wctx, const char *filename)
|
| 2111 | 2146 | if (ret < 0) |
| 2112 | 2147 | return ret; |
| 2113 | 2148 | |
| | 2149 | #define CHECK_END if (ret < 0) goto end |
| | 2150 | |
| 2114 | 2151 | nb_streams_frames = av_calloc(fmt_ctx->nb_streams, sizeof(*nb_streams_frames)); |
| 2115 | 2152 | nb_streams_packets = av_calloc(fmt_ctx->nb_streams, sizeof(*nb_streams_packets)); |
| 2116 | 2153 | selected_streams = av_calloc(fmt_ctx->nb_streams, sizeof(*selected_streams)); |
| … |
… |
static int probe_file(WriterContext *wctx, const char *filename)
|
| 2120 | 2157 | ret = avformat_match_stream_specifier(fmt_ctx, |
| 2121 | 2158 | fmt_ctx->streams[i], |
| 2122 | 2159 | stream_specifier); |
| 2123 | | if (ret < 0) |
| 2124 | | goto end; |
| | 2160 | CHECK_END; |
| 2125 | 2161 | else |
| 2126 | 2162 | selected_streams[i] = ret; |
| 2127 | 2163 | ret = 0; |
| … |
… |
static int probe_file(WriterContext *wctx, const char *filename)
|
| 2140 | 2176 | section_id = SECTION_ID_FRAMES; |
| 2141 | 2177 | if (do_show_frames || do_show_packets) |
| 2142 | 2178 | writer_print_section_header(wctx, section_id); |
| 2143 | | read_packets(wctx, fmt_ctx); |
| | 2179 | ret = read_packets(wctx, fmt_ctx); |
| 2144 | 2180 | if (do_show_frames || do_show_packets) |
| 2145 | 2181 | writer_print_section_footer(wctx); |
| | 2182 | CHECK_END; |
| | 2183 | } |
| | 2184 | if (do_show_programs) { |
| | 2185 | ret = show_programs(wctx, fmt_ctx); |
| | 2186 | CHECK_END; |
| | 2187 | } |
| | 2188 | |
| | 2189 | if (do_show_streams) { |
| | 2190 | ret = show_streams(wctx, fmt_ctx); |
| | 2191 | CHECK_END; |
| | 2192 | } |
| | 2193 | if (do_show_chapters) { |
| | 2194 | ret = show_chapters(wctx, fmt_ctx); |
| | 2195 | CHECK_END; |
| | 2196 | } |
| | 2197 | if (do_show_format) { |
| | 2198 | ret = show_format(wctx, fmt_ctx); |
| | 2199 | CHECK_END; |
| 2146 | 2200 | } |
| 2147 | | if (do_show_programs) |
| 2148 | | show_programs(wctx, fmt_ctx); |
| 2149 | | if (do_show_streams) |
| 2150 | | show_streams(wctx, fmt_ctx); |
| 2151 | | if (do_show_chapters) |
| 2152 | | show_chapters(wctx, fmt_ctx); |
| 2153 | | if (do_show_format) |
| 2154 | | show_format(wctx, fmt_ctx); |
| 2155 | 2201 | |
| 2156 | 2202 | end: |
| 2157 | 2203 | close_input_file(&fmt_ctx); |