X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=ffprobe.c;h=fa608948336f07b52c5c35611bf87b32f4b64680;hb=6234fd2fa0123d8b6802a337d456cfb82ae57e49;hp=4a7ec0ad3111ceda9c74cff3e247cb25f4d2ca5b;hpb=78c52e2721cad97f4ac4a4a38c09e1cee2a4e7e2;p=ffmpeg diff --git a/ffprobe.c b/ffprobe.c index 4a7ec0ad311..fa608948336 100644 --- a/ffprobe.c +++ b/ffprobe.c @@ -51,6 +51,19 @@ #include "libpostproc/postprocess.h" #include "cmdutils.h" +#include "libavutil/thread.h" + +#if !HAVE_THREADS +# ifdef pthread_mutex_lock +# undef pthread_mutex_lock +# endif +# define pthread_mutex_lock(a) +# ifdef pthread_mutex_unlock +# undef pthread_mutex_unlock +# endif +# define pthread_mutex_unlock(a) +#endif + typedef struct InputStream { AVStream *st; @@ -86,6 +99,7 @@ static int do_show_library_versions = 0; static int do_show_pixel_formats = 0; static int do_show_pixel_format_flags = 0; static int do_show_pixel_format_components = 0; +static int do_show_log = 0; static int do_show_chapter_tags = 0; static int do_show_format_tags = 0; @@ -148,6 +162,8 @@ typedef enum { SECTION_ID_FRAME_TAGS, SECTION_ID_FRAME_SIDE_DATA_LIST, SECTION_ID_FRAME_SIDE_DATA, + SECTION_ID_FRAME_LOG, + SECTION_ID_FRAME_LOGS, SECTION_ID_LIBRARY_VERSION, SECTION_ID_LIBRARY_VERSIONS, SECTION_ID_PACKET, @@ -187,10 +203,12 @@ static struct section sections[] = { [SECTION_ID_FORMAT] = { SECTION_ID_FORMAT, "format", 0, { SECTION_ID_FORMAT_TAGS, -1 } }, [SECTION_ID_FORMAT_TAGS] = { SECTION_ID_FORMAT_TAGS, "tags", SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "format_tags" }, [SECTION_ID_FRAMES] = { SECTION_ID_FRAMES, "frames", SECTION_FLAG_IS_ARRAY, { SECTION_ID_FRAME, SECTION_ID_SUBTITLE, -1 } }, - [SECTION_ID_FRAME] = { SECTION_ID_FRAME, "frame", 0, { SECTION_ID_FRAME_TAGS, SECTION_ID_FRAME_SIDE_DATA_LIST, -1 } }, + [SECTION_ID_FRAME] = { SECTION_ID_FRAME, "frame", 0, { SECTION_ID_FRAME_TAGS, SECTION_ID_FRAME_SIDE_DATA_LIST, SECTION_ID_FRAME_LOGS, -1 } }, [SECTION_ID_FRAME_TAGS] = { SECTION_ID_FRAME_TAGS, "tags", SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "frame_tags" }, [SECTION_ID_FRAME_SIDE_DATA_LIST] ={ SECTION_ID_FRAME_SIDE_DATA_LIST, "side_data_list", SECTION_FLAG_IS_ARRAY, { SECTION_ID_FRAME_SIDE_DATA, -1 }, .element_name = "side_data", .unique_name = "frame_side_data_list" }, [SECTION_ID_FRAME_SIDE_DATA] = { SECTION_ID_FRAME_SIDE_DATA, "side_data", 0, { -1 } }, + [SECTION_ID_FRAME_LOGS] = { SECTION_ID_FRAME_LOGS, "logs", SECTION_FLAG_IS_ARRAY, { SECTION_ID_FRAME_LOG, -1 } }, + [SECTION_ID_FRAME_LOG] = { SECTION_ID_FRAME_LOG, "log", 0, { -1 }, }, [SECTION_ID_LIBRARY_VERSIONS] = { SECTION_ID_LIBRARY_VERSIONS, "library_versions", SECTION_FLAG_IS_ARRAY, { SECTION_ID_LIBRARY_VERSION, -1 } }, [SECTION_ID_LIBRARY_VERSION] = { SECTION_ID_LIBRARY_VERSION, "library_version", 0, { -1 } }, [SECTION_ID_PACKETS] = { SECTION_ID_PACKETS, "packets", SECTION_FLAG_IS_ARRAY, { SECTION_ID_PACKET, -1} }, @@ -257,11 +275,79 @@ static uint64_t *nb_streams_packets; static uint64_t *nb_streams_frames; static int *selected_streams; +#if HAVE_THREADS +pthread_mutex_t log_mutex; +#endif +typedef struct LogBuffer { + char *context_name; + int log_level; + char *log_message; + AVClassCategory category; + char *parent_name; + AVClassCategory parent_category; +}LogBuffer; + +static LogBuffer *log_buffer; +static int log_buffer_size; + +static void log_callback(void *ptr, int level, const char *fmt, va_list vl) +{ + AVClass* avc = ptr ? *(AVClass **) ptr : NULL; + va_list vl2; + char line[1024]; + static int print_prefix = 1; + void *new_log_buffer; + + va_copy(vl2, vl); + av_log_default_callback(ptr, level, fmt, vl); + av_log_format_line(ptr, level, fmt, vl2, line, sizeof(line), &print_prefix); + va_end(vl2); + +#if HAVE_THREADS + pthread_mutex_lock(&log_mutex); + + new_log_buffer = av_realloc_array(log_buffer, log_buffer_size + 1, sizeof(*log_buffer)); + if (new_log_buffer) { + char *msg; + int i; + + log_buffer = new_log_buffer; + memset(&log_buffer[log_buffer_size], 0, sizeof(log_buffer[log_buffer_size])); + log_buffer[log_buffer_size].context_name= avc ? av_strdup(avc->item_name(ptr)) : NULL; + if (avc) { + if (avc->get_category) log_buffer[log_buffer_size].category = avc->get_category(ptr); + else log_buffer[log_buffer_size].category = avc->category; + } + log_buffer[log_buffer_size].log_level = level; + msg = log_buffer[log_buffer_size].log_message = av_strdup(line); + for (i=strlen(msg) - 1; i>=0 && msg[i] == '\n'; i--) { + msg[i] = 0; + } + if (avc && avc->parent_log_context_offset) { + AVClass** parent = *(AVClass ***) (((uint8_t *) ptr) + + avc->parent_log_context_offset); + if (parent && *parent) { + log_buffer[log_buffer_size].parent_name = av_strdup((*parent)->item_name(parent)); + log_buffer[log_buffer_size].parent_category = + (*parent)->get_category ? (*parent)->get_category(parent) :(*parent)->category; + } + } + log_buffer_size ++; + } + + pthread_mutex_unlock(&log_mutex); +#endif +} + static void ffprobe_cleanup(int ret) { int i; for (i = 0; i < FF_ARRAY_ELEMS(sections); i++) av_dict_free(&(sections[i].entries_to_show)); + +#if HAVE_THREADS + pthread_mutex_destroy(&log_mutex); +#endif } struct unit_value { @@ -1770,12 +1856,12 @@ static void print_pkt_side_data(WriterContext *w, { int i; - writer_print_section_header(w, SECTION_ID_STREAM_SIDE_DATA_LIST); + writer_print_section_header(w, id_data_list); for (i = 0; i < nb_side_data; i++) { const AVPacketSideData *sd = &side_data[i]; const char *name = av_packet_side_data_name(sd->type); - writer_print_section_header(w, SECTION_ID_STREAM_SIDE_DATA); + writer_print_section_header(w, id_data); print_str("side_data_type", name ? name : "unknown"); if (sd->type == AV_PKT_DATA_DISPLAYMATRIX && sd->size >= 9*4) { writer_print_integers(w, "displaymatrix", sd->data, 9, " %11d", 3, 4, 1); @@ -1806,12 +1892,68 @@ static void print_pkt_side_data(WriterContext *w, print_int("yaw", (double) spherical->yaw / (1 << 16)); print_int("pitch", (double) spherical->pitch / (1 << 16)); print_int("roll", (double) spherical->roll / (1 << 16)); + } else if (sd->type == AV_PKT_DATA_SKIP_SAMPLES && sd->size == 10) { + print_int("skip_samples", AV_RL32(sd->data)); + print_int("discard_padding", AV_RL32(sd->data + 4)); + print_int("skip_reason", AV_RL8(sd->data + 8)); + print_int("discard_reason", AV_RL8(sd->data + 9)); } writer_print_section_footer(w); } writer_print_section_footer(w); } +static void clear_log(int need_lock) +{ + int i; + + if (need_lock) + pthread_mutex_lock(&log_mutex); + for (i=0; inb_side_data) { writer_print_section_header(w, SECTION_ID_FRAME_SIDE_DATA_LIST); for (i = 0; i < frame->nb_side_data; i++) { @@ -1998,6 +2142,7 @@ static av_always_inline int process_frame(WriterContext *w, AVSubtitle sub; int ret = 0, got_frame = 0; + clear_log(1); if (dec_ctx && dec_ctx->codec) { switch (par->codec_type) { case AVMEDIA_TYPE_VIDEO: @@ -2237,9 +2382,8 @@ static int show_stream(WriterContext *w, AVFormatContext *fmt_ctx, int stream_id #endif /* print AVI/FourCC tag */ - av_get_codec_tag_string(val_str, sizeof(val_str), par->codec_tag); - print_str("codec_tag_string", val_str); - print_fmt("codec_tag", "0x%04x", par->codec_tag); + print_str("codec_tag_string", av_fourcc2str(par->codec_tag)); + print_fmt("codec_tag", "0x%04"PRIx32, par->codec_tag); switch (par->codec_type) { case AVMEDIA_TYPE_VIDEO: @@ -2655,6 +2799,13 @@ static int open_input_file(InputFile *ifile, const char *filename) if (err < 0) exit(1); + if (do_show_log) { + // For loging it is needed to disable at least frame threads as otherwise + // the log information would need to be reordered and matches up to contexts and frames + // That is in fact possible but not trivial + av_dict_set(&codec_opts, "threads", "1", 0); + } + av_codec_set_pkt_timebase(ist->dec_ctx, stream->time_base); ist->dec_ctx->framerate = stream->avg_frame_rate; @@ -3240,6 +3391,9 @@ static const OptionDef real_options[] = { "show a particular entry from the format/container info", "entry" }, { "show_entries", HAS_ARG, {.func_arg = opt_show_entries}, "show a set of specified entries", "entry_list" }, +#if HAVE_THREADS + { "show_log", OPT_INT|HAS_ARG, {(void*)&do_show_log}, "show log" }, +#endif { "show_packets", 0, {(void*)&opt_show_packets}, "show packets info" }, { "show_programs", 0, {(void*)&opt_show_programs}, "show programs info" }, { "show_streams", 0, {(void*)&opt_show_streams}, "show streams info" }, @@ -3286,6 +3440,14 @@ int main(int argc, char **argv) init_dynload(); +#if HAVE_THREADS + ret = pthread_mutex_init(&log_mutex, NULL); + if (ret != 0) { + goto end; + } +#endif + av_log_set_callback(log_callback); + av_log_set_flags(AV_LOG_SKIP_REPEATED); register_exit(ffprobe_cleanup);