]> git.sesse.net Git - ffmpeg/blobdiff - libavformat/hashenc.c
avfilter/vf_fieldhint: Assert that mode is valid
[ffmpeg] / libavformat / hashenc.c
index 614c8157a57ee6cf4b5a399eec7c2f2d31741982..a66db4ae715b4315745ff434daf5b6cafe0c5c7f 100644 (file)
@@ -22,6 +22,7 @@
 #include "libavutil/avassert.h"
 #include "libavutil/avstring.h"
 #include "libavutil/hash.h"
+#include "libavutil/intreadwrite.h"
 #include "libavutil/opt.h"
 #include "avformat.h"
 #include "internal.h"
@@ -33,31 +34,12 @@ struct HashContext {
     int format_version;
 };
 
-static void hash_finish(struct AVFormatContext *s, char *buf)
-{
-    struct HashContext *c = s->priv_data;
-    uint8_t hash[AV_HASH_MAX_SIZE];
-    int i, offset = strlen(buf);
-    int len = av_hash_get_size(c->hash);
-    av_assert0(len > 0 && len <= sizeof(hash));
-    av_hash_final(c->hash, hash);
-    for (i = 0; i < len; i++) {
-        snprintf(buf + offset, 3, "%02"PRIx8, hash[i]);
-        offset += 2;
-    }
-    buf[offset] = '\n';
-    buf[offset+1] = 0;
-
-    avio_write(s->pb, buf, strlen(buf));
-    avio_flush(s->pb);
-}
-
 #define OFFSET(x) offsetof(struct HashContext, x)
 #define ENC AV_OPT_FLAG_ENCODING_PARAM
 #if CONFIG_HASH_MUXER || CONFIG_FRAMEHASH_MUXER
 static const AVOption hash_options[] = {
     { "hash", "set hash to use", OFFSET(hash_name), AV_OPT_TYPE_STRING, {.str = "sha256"}, 0, 0, ENC },
-    { "format_version", "file format version", OFFSET(format_version), AV_OPT_TYPE_INT, {.i64 = 1}, 1, 2, ENC },
+    { "format_version", "file format version", OFFSET(format_version), AV_OPT_TYPE_INT, {.i64 = 2}, 1, 2, ENC },
     { NULL },
 };
 #endif
@@ -65,7 +47,7 @@ static const AVOption hash_options[] = {
 #if CONFIG_MD5_MUXER || CONFIG_FRAMEMD5_MUXER
 static const AVOption md5_options[] = {
     { "hash", "set hash to use", OFFSET(hash_name), AV_OPT_TYPE_STRING, {.str = "md5"}, 0, 0, ENC },
-    { "format_version", "file format version", OFFSET(format_version), AV_OPT_TYPE_INT, {.i64 = 1}, 1, 2, ENC },
+    { "format_version", "file format version", OFFSET(format_version), AV_OPT_TYPE_INT, {.i64 = 2}, 1, 2, ENC },
     { NULL },
 };
 #endif
@@ -91,11 +73,13 @@ static int hash_write_packet(struct AVFormatContext *s, AVPacket *pkt)
 static int hash_write_trailer(struct AVFormatContext *s)
 {
     struct HashContext *c = s->priv_data;
-    char buf[256];
-    av_strlcpy(buf, av_hash_get_name(c->hash), sizeof(buf) - 200);
-    av_strlcat(buf, "=", sizeof(buf) - 200);
+    char buf[AV_HASH_MAX_SIZE*2+128];
+    snprintf(buf, sizeof(buf) - 200, "%s=", av_hash_get_name(c->hash));
 
-    hash_finish(s, buf);
+    av_hash_final_hex(c->hash, 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->hash);
     return 0;
@@ -149,6 +133,27 @@ AVOutputFormat ff_md5_muxer = {
 #endif
 
 #if CONFIG_FRAMEHASH_MUXER || CONFIG_FRAMEMD5_MUXER
+static void framehash_print_extradata(struct AVFormatContext *s)
+{
+    int i;
+
+    for (i = 0; i < s->nb_streams; i++) {
+        AVStream *st = s->streams[i];
+        AVCodecParameters *par = st->codecpar;
+        if (par->extradata) {
+            struct HashContext *c = s->priv_data;
+            char buf[AV_HASH_MAX_SIZE*2+1];
+
+            avio_printf(s->pb, "#extradata %d, %31d, ", i, par->extradata_size);
+            av_hash_init(c->hash);
+            av_hash_update(c->hash, par->extradata, par->extradata_size);
+            av_hash_final_hex(c->hash, buf, sizeof(buf));
+            avio_write(s->pb, buf, strlen(buf));
+            avio_printf(s->pb, "\n");
+        }
+    }
+}
+
 static int framehash_write_header(struct AVFormatContext *s)
 {
     struct HashContext *c = s->priv_data;
@@ -158,7 +163,8 @@ static int framehash_write_header(struct AVFormatContext *s)
     avio_printf(s->pb, "#format: frame checksums\n");
     avio_printf(s->pb, "#version: %d\n", c->format_version);
     avio_printf(s->pb, "#hash: %s\n", av_hash_get_name(c->hash));
-    ff_framehash_write_header(s, c->format_version);
+    framehash_print_extradata(s);
+    ff_framehash_write_header(s);
     avio_printf(s->pb, "#stream#, dts,        pts, duration,     size, hash\n");
     return 0;
 }
@@ -166,13 +172,38 @@ static int framehash_write_header(struct AVFormatContext *s)
 static int framehash_write_packet(struct AVFormatContext *s, AVPacket *pkt)
 {
     struct HashContext *c = s->priv_data;
-    char buf[256];
+    char buf[AV_HASH_MAX_SIZE*2+128];
+    int len;
     av_hash_init(c->hash);
     av_hash_update(c->hash, pkt->data, pkt->size);
 
-    snprintf(buf, sizeof(buf) - 64, "%d, %10"PRId64", %10"PRId64", %8"PRId64", %8d, ",
+    snprintf(buf, sizeof(buf) - (AV_HASH_MAX_SIZE * 2 + 1), "%d, %10"PRId64", %10"PRId64", %8"PRId64", %8d, ",
              pkt->stream_index, pkt->dts, pkt->pts, pkt->duration, pkt->size);
-    hash_finish(s, buf);
+    len = strlen(buf);
+    av_hash_final_hex(c->hash, buf + len, sizeof(buf) - len);
+    avio_write(s->pb, buf, strlen(buf));
+
+    if (c->format_version > 1 && pkt->side_data_elems) {
+        int i, j;
+        avio_printf(s->pb, ", S=%d", pkt->side_data_elems);
+        for (i = 0; i < pkt->side_data_elems; i++) {
+            av_hash_init(c->hash);
+            if (HAVE_BIGENDIAN && pkt->side_data[i].type == AV_PKT_DATA_PALETTE) {
+                for (j = 0; j < pkt->side_data[i].size; j += sizeof(uint32_t)) {
+                    uint32_t data = AV_RL32(pkt->side_data[i].data + j);
+                    av_hash_update(c->hash, (uint8_t *)&data, sizeof(uint32_t));
+                }
+            } else
+                av_hash_update(c->hash, pkt->side_data[i].data, pkt->side_data[i].size);
+            snprintf(buf, sizeof(buf) - (AV_HASH_MAX_SIZE * 2 + 1), ", %8d, ", pkt->side_data[i].size);
+            len = strlen(buf);
+            av_hash_final_hex(c->hash, buf + len, sizeof(buf) - len);
+            avio_write(s->pb, buf, strlen(buf));
+        }
+    }
+
+    avio_printf(s->pb, "\n");
+    avio_flush(s->pb);
     return 0;
 }