Non-frame based muxers only, the frame based ones are already per stream. Signed-off-by: Moritz Barsnick <barsn...@gmx.net> --- doc/muxers.texi | 5 +++++ libavformat/hashenc.c | 41 +++++++++++++++++++++++++++++------------ 2 files changed, 34 insertions(+), 12 deletions(-)
diff --git a/doc/muxers.texi b/doc/muxers.texi index bc38cf6029..34ca7f07cb 100644 --- a/doc/muxers.texi +++ b/doc/muxers.texi @@ -511,6 +511,11 @@ Supported values include @code{MD5}, @code{murmur3}, @code{RIPEMD128}, @code{SHA224}, @code{SHA256} (default), @code{SHA512/224}, @code{SHA512/256}, @code{SHA384}, @code{SHA512}, @code{CRC32} and @code{adler32}. +@item per_stream @var{bool} +Whether to calculate a hash per stream, instead of combined over all +packets' payload. Each stream's hash is prefixed with its stream index. +Default is @code{false}. + @end table @subsection Examples diff --git a/libavformat/hashenc.c b/libavformat/hashenc.c index 96e00f580c..394b8a0fce 100644 --- a/libavformat/hashenc.c +++ b/libavformat/hashenc.c @@ -31,6 +31,7 @@ struct HashContext { const AVClass *avclass; struct AVHashContext **hashes; char *hash_name; + int per_stream; int format_version; }; @@ -40,10 +41,13 @@ struct HashContext { { "hash", "set hash to use", OFFSET(hash_name), AV_OPT_TYPE_STRING, {.str = defaulttype}, 0, 0, ENC } #define FORMAT_VERSION_OPT \ { "format_version", "file format version", OFFSET(format_version), AV_OPT_TYPE_INT, {.i64 = 2}, 1, 2, ENC } +#define PER_STREAM_OPT \ + { "per_stream", "whether to calculate a hash per stream", OFFSET(per_stream), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, ENC } #if CONFIG_HASH_MUXER static const AVOption hash_options[] = { HASH_OPT("sha256"), + PER_STREAM_OPT, { NULL }, }; #endif @@ -59,6 +63,7 @@ static const AVOption framehash_options[] = { #if CONFIG_MD5_MUXER static const AVOption md5_options[] = { HASH_OPT("md5"), + PER_STREAM_OPT, { NULL }, }; #endif @@ -74,39 +79,51 @@ static const AVOption framemd5_options[] = { #if CONFIG_HASH_MUXER || CONFIG_MD5_MUXER static int hash_write_header(struct AVFormatContext *s) { - int res; + int i, res; struct HashContext *c = s->priv_data; - c->hashes = av_malloc_array(1, sizeof(c->hashes)); + int num_hashes = c->per_stream ? s->nb_streams : 1; + c->hashes = av_malloc_array(num_hashes, sizeof(c->hashes)); if (!c->hashes) return AVERROR(ENOMEM); - res = av_hash_alloc(&c->hashes[0], c->hash_name); - if (res < 0) { - av_freep(&c->hashes); - return res; + for (i = 0; i < num_hashes; i++) { + res = av_hash_alloc(&c->hashes[i], c->hash_name); + if (res < 0) + goto err; + av_hash_init(c->hashes[i]); } - av_hash_init(c->hashes[0]); return 0; +err: + for (int j = 0; j < i; j++) + av_hash_freep(&c->hashes[j]); + av_freep(&c->hashes); + return res; } static int hash_write_packet(struct AVFormatContext *s, AVPacket *pkt) { struct HashContext *c = s->priv_data; - av_hash_update(c->hashes[0], pkt->data, pkt->size); + av_hash_update(c->hashes[c->per_stream ? pkt->stream_index : 0], pkt->data, pkt->size); return 0; } static int hash_write_trailer(struct AVFormatContext *s) { struct HashContext *c = s->priv_data; + int num_hashes = c->per_stream ? s->nb_streams : 1; + for (int i = 0; i < num_hashes; i++) { char buf[AV_HASH_MAX_SIZE*2+128]; - snprintf(buf, sizeof(buf) - 200, "%s=", av_hash_get_name(c->hashes[0])); - - av_hash_final_hex(c->hashes[0], buf + strlen(buf), sizeof(buf) - strlen(buf)); + if (c->per_stream) { + snprintf(buf, sizeof(buf) - 200, "%d,%s=", i, av_hash_get_name(c->hashes[i])); + } else { + snprintf(buf, sizeof(buf) - 200, "%s=", av_hash_get_name(c->hashes[i])); + } + av_hash_final_hex(c->hashes[i], buf + strlen(buf), sizeof(buf) - strlen(buf)); av_strlcatf(buf, sizeof(buf), "\n"); avio_write(s->pb, buf, strlen(buf)); avio_flush(s->pb); - av_hash_freep(&c->hashes[0]); + av_hash_freep(&c->hashes[i]); + } av_freep(&c->hashes); return 0; } -- 2.20.1 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".