[FFmpeg-devel] [PATCH 3/4] avformat/hashenc: add option to create hash per stream
Moritz Barsnick
barsnick at gmx.net
Sun Aug 11 15:47:55 EEST 2019
Non-frame based muxers only, the frame based ones are already per
stream.
Signed-off-by: Moritz Barsnick <barsnick at 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}.
+ at 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
More information about the ffmpeg-devel
mailing list