[FFmpeg-devel] [PATCH] ffprobe: add -show_data_hash option.

Stefano Sabatini stefasab at gmail.com
Wed Apr 23 01:00:36 CEST 2014


On date Monday 2014-04-21 18:38:52 +0200, Nicolas George encoded:
> 
> Signed-off-by: Nicolas George <george at nsup.org>
> ---
>  doc/ffprobe.texi |    4 ++++
>  doc/ffprobe.xsd  |    2 ++
>  ffprobe.c        |   33 +++++++++++++++++++++++++++++++++
>  3 files changed, 39 insertions(+)
> 
> 
> With that, ffprobe can be used in FATE tests to test demuxers, including
> extradata and metadata.
> 
> 
> diff --git a/doc/ffprobe.texi b/doc/ffprobe.texi
> index 8de8956..bf6cc59 100644
> --- a/doc/ffprobe.texi
> +++ b/doc/ffprobe.texi
> @@ -119,6 +119,10 @@ Show payload data, as a hexadecimal and ASCII dump. Coupled with
>  
>  The dump is printed as the "data" field. It may contain newlines.
>  

> + at item -show_data_hash @var{algorithm}
> +Show a hash of payload data, for packets with @option{-show_packets} and for
> +codec extradata with @option{-show_streams}.

Probably listing the available hash algorithms would be helpful (or we
could expose that information programmatically/automatically).

> +
>  @item -show_error
>  Show information about the error found when trying to probe the input.
>  
> diff --git a/doc/ffprobe.xsd b/doc/ffprobe.xsd
> index 1bc1fb5..34a94ae 100644
> --- a/doc/ffprobe.xsd
> +++ b/doc/ffprobe.xsd
> @@ -50,6 +50,7 @@
>        <xsd:attribute name="pos"           type="xsd:long"  />
>        <xsd:attribute name="flags"         type="xsd:string" use="required" />
>        <xsd:attribute name="data"          type="xsd:string" />
> +      <xsd:attribute name="data_hash"     type="xsd:string" />
>      </xsd:complexType>
>  
>      <xsd:complexType name="frameType">
> @@ -138,6 +139,7 @@
>        <xsd:attribute name="codec_tag"        type="xsd:string" use="required"/>
>        <xsd:attribute name="codec_tag_string" type="xsd:string" use="required"/>
>        <xsd:attribute name="extradata"        type="xsd:string" />
> +      <xsd:attribute name="extradata_hash"   type="xsd:string" />
>  
>        <!-- video attributes -->
>        <xsd:attribute name="width"                type="xsd:int"/>
> diff --git a/ffprobe.c b/ffprobe.c
> index 9e39ff7..df0a797 100644
> --- a/ffprobe.c
> +++ b/ffprobe.c
> @@ -33,6 +33,7 @@
>  #include "libavutil/avassert.h"
>  #include "libavutil/avstring.h"
>  #include "libavutil/bprint.h"
> +#include "libavutil/hash.h"
>  #include "libavutil/opt.h"
>  #include "libavutil/pixdesc.h"
>  #include "libavutil/dict.h"
> @@ -80,6 +81,7 @@ static int show_private_data            = 1;
>  
>  static char *print_format;
>  static char *stream_specifier;
> +static char *show_data_hash;
>  
>  typedef struct {
>      int id;             ///< identifier
> @@ -183,6 +185,8 @@ static const OptionDef *options;
>  static const char *input_filename;
>  static AVInputFormat *iformat = NULL;
>  
> +static struct AVHashContext *hash;
> +
>  static const char *const binary_unit_prefixes [] = { "", "Ki", "Mi", "Gi", "Ti", "Pi" };
>  static const char *const decimal_unit_prefixes[] = { "", "K" , "M" , "G" , "T" , "P"  };
>  
> @@ -679,6 +683,21 @@ static void writer_print_data(WriterContext *wctx, const char *name,
>      av_bprint_finalize(&bp, NULL);
>  }
>  
> +static void writer_print_data_hash(WriterContext *wctx, const char *name,
> +                                   uint8_t *data, int size)
> +{
> +    char *p, buf[AV_HASH_MAX_SIZE * 2 + 64] = { 0 };
> +
> +    if (!hash)
> +        return;
> +    av_hash_init(hash);
> +    av_hash_update(hash, data, size);
> +    snprintf(buf, sizeof(buf), "%s:", av_hash_get_name(hash));
> +    p = buf + strlen(buf);
> +    av_hash_final_hex(hash, p, buf + sizeof(buf) - p);
> +    writer_print_string(wctx, name, buf, 0);
> +}
> +
>  #define MAX_REGISTERED_WRITERS_NB 64
>  
>  static const Writer *registered_writers[MAX_REGISTERED_WRITERS_NB + 1];
> @@ -1678,6 +1697,7 @@ static void show_packet(WriterContext *w, AVFormatContext *fmt_ctx, AVPacket *pk
>      print_fmt("flags", "%c",      pkt->flags & AV_PKT_FLAG_KEY ? 'K' : '_');
>      if (do_show_data)
>          writer_print_data(w, "data", pkt->data, pkt->size);
> +    writer_print_data_hash(w, "data_hash", pkt->data, pkt->size);
>      writer_print_section_footer(w);
>  
>      av_bprint_finalize(&pbuf, NULL);
> @@ -2108,6 +2128,8 @@ static int show_stream(WriterContext *w, AVFormatContext *fmt_ctx, int stream_id
>      if (do_show_data)
>          writer_print_data(w, "extradata", dec_ctx->extradata,
>                                            dec_ctx->extradata_size);
> +    writer_print_data_hash(w, "extradata_hash", dec_ctx->extradata,
> +                                                dec_ctx->extradata_size);
>  
>      /* Print disposition information */
>  #define PRINT_DISPOSITION(flagname, name) do {                                \
> @@ -2835,6 +2857,7 @@ static const OptionDef real_options[] = {
>      { "select_streams", OPT_STRING | HAS_ARG, {(void*)&stream_specifier}, "select the specified streams", "stream_specifier" },
>      { "sections", OPT_EXIT, {.func_arg = opt_sections}, "print sections structure and section information, and exit" },
>      { "show_data",    OPT_BOOL, {(void*)&do_show_data}, "show packets data" },
> +    { "show_data_hash", OPT_STRING | HAS_ARG, {(void*)&show_data_hash}, "show packets data hash" },
>      { "show_error",   0, {(void*)&opt_show_error},  "show probing error" },
>      { "show_format",  0, {(void*)&opt_show_format}, "show format/container info" },
>      { "show_frames",  0, {(void*)&opt_show_frames}, "show frames info" },
> @@ -2938,6 +2961,15 @@ int main(int argc, char **argv)
>      w_name = av_strtok(print_format, "=", &buf);
>      w_args = buf;
>  
> +    if (show_data_hash) {
> +        if ((ret = av_hash_alloc(&hash, show_data_hash)) < 0) {
> +            if (ret == AVERROR(EINVAL))
> +                av_log(NULL, AV_LOG_ERROR, "Unknown hash algorithm '%s'\n",
> +                       show_data_hash);
> +            goto end;
> +        }
> +    }
> +
>      w = writer_get_by_name(w_name);
>      if (!w) {
>          av_log(NULL, AV_LOG_ERROR, "Unknown output format with name '%s'\n", w_name);
> @@ -2977,6 +3009,7 @@ int main(int argc, char **argv)
>  end:
>      av_freep(&print_format);
>      av_freep(&read_intervals);
> +    av_hash_freep(&hash);
>  
>      uninit_opts();
>      for (i = 0; i < FF_ARRAY_ELEMS(sections); i++)

LGTM otherwise and good idea (I fancied to implement that several
times), thanks.
-- 
FFmpeg = Furious & Faithless Merciless Programmable Ephemeral Gargoyle


More information about the ffmpeg-devel mailing list