Signed-off-by: Remko Tronçon <re...@el-tramo.be> --- This patch introduces a new 'streammd5' muxer. Similarly to the 'md5' and 'framemd5' muxer, it is used to compute the hash of media. However, I needed something in between both, to be able to quickly see which streams are identical across different files.
I did not add any tests yet, because I was not sure if there was general interest in this patch. Changelog | 1 + doc/muxers.texi | 40 ++++++++++++++++++++-- libavformat/Makefile | 1 + libavformat/allformats.c | 1 + libavformat/md5enc.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++++ libavformat/version.h | 4 +-- 6 files changed, 130 insertions(+), 4 deletions(-) diff --git a/Changelog b/Changelog index 7d672fb..42ee96a 100644 --- a/Changelog +++ b/Changelog @@ -6,6 +6,7 @@ version <next>: - fieldhint filter - loop video filter and aloop audio filter - Bob Weaver deinterlacing filter +- streammd5 format version 3.0: diff --git a/doc/muxers.texi b/doc/muxers.texi index f2ad7fe..1521f37 100644 --- a/doc/muxers.texi +++ b/doc/muxers.texi @@ -207,7 +207,7 @@ To print the information to stdout, use the command: ffmpeg -i INPUT -f framemd5 - @end example -See also the @ref{md5} muxer. +See also the @ref{md5} and @ref{streammd5} muxers. @anchor{gif} @section gif @@ -641,7 +641,7 @@ You can print the MD5 to stdout with the command: ffmpeg -i INPUT -f md5 - @end example -See also the @ref{framemd5} muxer. +See also the @ref{framemd5} and @ref{streammd5} muxers. @section mov, mp4, ismv @@ -1307,6 +1307,42 @@ Specify whether to remove all fragments when finished. Default 0 (do not remove) @end table +@anchor{streammd5} +@section streammd5 + +Per-stream MD5 testing format. + +This muxer computes and prints the MD5 hash for each stream. +By default audio streams are converted to signed +16-bit raw audio and video streams to raw video before computing the +hash. + +The output of the muxer consists of a line for each stream of the form: +@example +@var{stream_index}, @var{MD5} +@end example + +@var{MD5} is a hexadecimal number representing the computed MD5 hash +for the packet. + +@subsection Examples + +For example to compute the MD5 of all the audio and video streams in +@file{INPUT}, converted to raw audio and video packets, and store it +in the file @file{out.md5}: +@example +ffmpeg -i INPUT -f streammd5 out.md5 +@end example + +To compute the MD5 of all the streams in @file{INPUT} without any +conversion, and print it to stdout: +@example +ffmpeg -i INPUT -f streammd5 -codec copy -map 0 - +@end example + +See also the @ref{md5} and @ref{framemd5} muxers. + + @section tee The tee muxer can be used to write the same data to several files or any diff --git a/libavformat/Makefile b/libavformat/Makefile index 001b3f1..fde64dc 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -430,6 +430,7 @@ OBJS-$(CONFIG_SRT_DEMUXER) += srtdec.o subtitles.o OBJS-$(CONFIG_SRT_MUXER) += srtenc.o OBJS-$(CONFIG_STL_DEMUXER) += stldec.o subtitles.o OBJS-$(CONFIG_STR_DEMUXER) += psxstr.o +OBJS-$(CONFIG_STREAMMD5_MUXER) += md5enc.o OBJS-$(CONFIG_SUBVIEWER1_DEMUXER) += subviewer1dec.o subtitles.o OBJS-$(CONFIG_SUBVIEWER_DEMUXER) += subviewerdec.o subtitles.o OBJS-$(CONFIG_SUP_DEMUXER) += supdec.o diff --git a/libavformat/allformats.c b/libavformat/allformats.c index 02bb16a..df4c8eb 100644 --- a/libavformat/allformats.c +++ b/libavformat/allformats.c @@ -295,6 +295,7 @@ void av_register_all(void) REGISTER_MUXDEMUX(SPDIF, spdif); REGISTER_MUXDEMUX(SRT, srt); REGISTER_DEMUXER (STR, str); + REGISTER_MUXER (STREAMMD5, streammd5); REGISTER_DEMUXER (STL, stl); REGISTER_DEMUXER (SUBVIEWER1, subviewer1); REGISTER_DEMUXER (SUBVIEWER, subviewer); diff --git a/libavformat/md5enc.c b/libavformat/md5enc.c index 8433be4..b114a9b 100644 --- a/libavformat/md5enc.c +++ b/libavformat/md5enc.c @@ -169,3 +169,90 @@ AVOutputFormat ff_framemd5_muxer = { .priv_class = &framemd5_class, }; #endif + + +#if CONFIG_STREAMMD5_MUXER + +struct StreamMD5Context { + const AVClass *avclass; + struct AVHashContext** hashes; + char *hash_name; + int format_version; +}; + +static const AVClass streammd5enc_class = { + .class_name = "stream hash encoder class", + .item_name = av_default_item_name, + .option = hash_options, + .version = LIBAVUTIL_VERSION_INT, +}; + +static int streammd5_write_header(struct AVFormatContext *s) +{ + unsigned int i; + struct StreamMD5Context *ctx = s->priv_data; + ctx->hashes = av_calloc(s->nb_streams, sizeof(struct AVHashContext*)); + for (i = 0; i < s->nb_streams; ++i) { + int res = av_hash_alloc(&ctx->hashes[i], ctx->hash_name); + if (res < 0) { + return res; + } + av_hash_init(ctx->hashes[i]); + } + return 0; +} + +static int streammd5_write_packet(struct AVFormatContext *s, AVPacket *pkt) +{ + struct StreamMD5Context *ctx = s->priv_data; + av_hash_update(ctx->hashes[pkt->stream_index], pkt->data, pkt->size); + return 0; +} + +static int streammd5_write_trailer(struct AVFormatContext *s) +{ + struct StreamMD5Context *ctx = s->priv_data; + unsigned int i; + for (i = 0; i < s->nb_streams; ++i) { + int j = 0; + int len = 0; + int offset = 0; + char buf[256]; + uint8_t md5[AV_HASH_MAX_SIZE]; + + snprintf(buf, sizeof(buf), "%d, ", i); + + offset = strlen(buf); + len = av_hash_get_size(ctx->hashes[i]); + av_assert0(len > 0 && len <= sizeof(md5)); + av_hash_final(ctx->hashes[i], md5); + for (j = 0; j < len; j++) { + snprintf(buf + offset, 3, "%02"PRIx8, md5[j]); + offset += 2; + } + buf[offset] = '\n'; + buf[offset+1] = 0; + + avio_write(s->pb, buf, strlen(buf)); + avio_flush(s->pb); + + av_hash_freep(&ctx->hashes[i]); + } + av_freep(ctx->hashes); + return 0; +} + +AVOutputFormat ff_streammd5_muxer = { + .name = "streammd5", + .long_name = NULL_IF_CONFIG_SMALL("Per-stream MD5 testing"), + .priv_data_size = sizeof(struct StreamMD5Context), + .audio_codec = AV_CODEC_ID_PCM_S16LE, + .video_codec = AV_CODEC_ID_RAWVIDEO, + .write_header = streammd5_write_header, + .write_packet = streammd5_write_packet, + .write_trailer = streammd5_write_trailer, + .flags = AVFMT_VARIABLE_FPS | AVFMT_TS_NONSTRICT | + AVFMT_TS_NEGATIVE, + .priv_class = &streammd5enc_class, +}; +#endif diff --git a/libavformat/version.h b/libavformat/version.h index 62050a2..8fc8e77 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -30,8 +30,8 @@ #include "libavutil/version.h" #define LIBAVFORMAT_VERSION_MAJOR 57 -#define LIBAVFORMAT_VERSION_MINOR 25 -#define LIBAVFORMAT_VERSION_MICRO 101 +#define LIBAVFORMAT_VERSION_MINOR 26 +#define LIBAVFORMAT_VERSION_MICRO 100 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ LIBAVFORMAT_VERSION_MINOR, \ -- 2.1.0 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel