FFmpeg
hashenc.c
Go to the documentation of this file.
1 /*
2  * Hash/MD5 encoder (for codec/format testing)
3  * Copyright (c) 2009 Reimar Döffinger, based on crcenc (c) 2002 Fabrice Bellard
4  *
5  * This file is part of FFmpeg.
6  *
7  * FFmpeg is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * FFmpeg is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with FFmpeg; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21 
22 #include "libavutil/avassert.h"
23 #include "libavutil/avstring.h"
24 #include "libavutil/hash.h"
25 #include "libavutil/intreadwrite.h"
26 #include "libavutil/opt.h"
27 #include "avformat.h"
28 #include "internal.h"
29 
30 struct HashContext {
31  const AVClass *avclass;
33  char *hash_name;
35 };
36 
37 #define OFFSET(x) offsetof(struct HashContext, x)
38 #define ENC AV_OPT_FLAG_ENCODING_PARAM
39 #if CONFIG_HASH_MUXER || CONFIG_FRAMEHASH_MUXER
40 static const AVOption hash_options[] = {
41  { "hash", "set hash to use", OFFSET(hash_name), AV_OPT_TYPE_STRING, {.str = "sha256"}, 0, 0, ENC },
42  { "format_version", "file format version", OFFSET(format_version), AV_OPT_TYPE_INT, {.i64 = 2}, 1, 2, ENC },
43  { NULL },
44 };
45 #endif
46 
47 #if CONFIG_MD5_MUXER || CONFIG_FRAMEMD5_MUXER
48 static const AVOption md5_options[] = {
49  { "hash", "set hash to use", OFFSET(hash_name), AV_OPT_TYPE_STRING, {.str = "md5"}, 0, 0, ENC },
50  { "format_version", "file format version", OFFSET(format_version), AV_OPT_TYPE_INT, {.i64 = 2}, 1, 2, ENC },
51  { NULL },
52 };
53 #endif
54 
55 #if CONFIG_HASH_MUXER || CONFIG_MD5_MUXER
56 static int hash_write_header(struct AVFormatContext *s)
57 {
58  struct HashContext *c = s->priv_data;
59  int res = av_hash_alloc(&c->hash, c->hash_name);
60  if (res < 0)
61  return res;
62  av_hash_init(c->hash);
63  return 0;
64 }
65 
66 static int hash_write_packet(struct AVFormatContext *s, AVPacket *pkt)
67 {
68  struct HashContext *c = s->priv_data;
69  av_hash_update(c->hash, pkt->data, pkt->size);
70  return 0;
71 }
72 
73 static int hash_write_trailer(struct AVFormatContext *s)
74 {
75  struct HashContext *c = s->priv_data;
76  char buf[AV_HASH_MAX_SIZE*2+128];
77  snprintf(buf, sizeof(buf) - 200, "%s=", av_hash_get_name(c->hash));
78 
79  av_hash_final_hex(c->hash, buf + strlen(buf), sizeof(buf) - strlen(buf));
80  av_strlcatf(buf, sizeof(buf), "\n");
81  avio_write(s->pb, buf, strlen(buf));
82  avio_flush(s->pb);
83 
84  av_hash_freep(&c->hash);
85  return 0;
86 }
87 #endif
88 
89 #if CONFIG_HASH_MUXER
90 static const AVClass hashenc_class = {
91  .class_name = "hash muxer",
92  .item_name = av_default_item_name,
93  .option = hash_options,
94  .version = LIBAVUTIL_VERSION_INT,
95 };
96 
98  .name = "hash",
99  .long_name = NULL_IF_CONFIG_SMALL("Hash testing"),
100  .priv_data_size = sizeof(struct HashContext),
101  .audio_codec = AV_CODEC_ID_PCM_S16LE,
102  .video_codec = AV_CODEC_ID_RAWVIDEO,
103  .write_header = hash_write_header,
104  .write_packet = hash_write_packet,
105  .write_trailer = hash_write_trailer,
108  .priv_class = &hashenc_class,
109 };
110 #endif
111 
112 #if CONFIG_MD5_MUXER
113 static const AVClass md5enc_class = {
114  .class_name = "MD5 muxer",
115  .item_name = av_default_item_name,
116  .option = md5_options,
117  .version = LIBAVUTIL_VERSION_INT,
118 };
119 
121  .name = "md5",
122  .long_name = NULL_IF_CONFIG_SMALL("MD5 testing"),
123  .priv_data_size = sizeof(struct HashContext),
124  .audio_codec = AV_CODEC_ID_PCM_S16LE,
125  .video_codec = AV_CODEC_ID_RAWVIDEO,
126  .write_header = hash_write_header,
127  .write_packet = hash_write_packet,
128  .write_trailer = hash_write_trailer,
131  .priv_class = &md5enc_class,
132 };
133 #endif
134 
135 #if CONFIG_FRAMEHASH_MUXER || CONFIG_FRAMEMD5_MUXER
136 static void framehash_print_extradata(struct AVFormatContext *s)
137 {
138  int i;
139 
140  for (i = 0; i < s->nb_streams; i++) {
141  AVStream *st = s->streams[i];
142  AVCodecParameters *par = st->codecpar;
143  if (par->extradata) {
144  struct HashContext *c = s->priv_data;
145  char buf[AV_HASH_MAX_SIZE*2+1];
146 
147  avio_printf(s->pb, "#extradata %d, %31d, ", i, par->extradata_size);
148  av_hash_init(c->hash);
149  av_hash_update(c->hash, par->extradata, par->extradata_size);
150  av_hash_final_hex(c->hash, buf, sizeof(buf));
151  avio_write(s->pb, buf, strlen(buf));
152  avio_printf(s->pb, "\n");
153  }
154  }
155 }
156 
157 static int framehash_write_header(struct AVFormatContext *s)
158 {
159  struct HashContext *c = s->priv_data;
160  int res = av_hash_alloc(&c->hash, c->hash_name);
161  if (res < 0)
162  return res;
163  avio_printf(s->pb, "#format: frame checksums\n");
164  avio_printf(s->pb, "#version: %d\n", c->format_version);
165  avio_printf(s->pb, "#hash: %s\n", av_hash_get_name(c->hash));
166  framehash_print_extradata(s);
168  avio_printf(s->pb, "#stream#, dts, pts, duration, size, hash\n");
169  return 0;
170 }
171 
172 static int framehash_write_packet(struct AVFormatContext *s, AVPacket *pkt)
173 {
174  struct HashContext *c = s->priv_data;
175  char buf[AV_HASH_MAX_SIZE*2+128];
176  int len;
177  av_hash_init(c->hash);
178  av_hash_update(c->hash, pkt->data, pkt->size);
179 
180  snprintf(buf, sizeof(buf) - (AV_HASH_MAX_SIZE * 2 + 1), "%d, %10"PRId64", %10"PRId64", %8"PRId64", %8d, ",
182  len = strlen(buf);
183  av_hash_final_hex(c->hash, buf + len, sizeof(buf) - len);
184  avio_write(s->pb, buf, strlen(buf));
185 
186  if (c->format_version > 1 && pkt->side_data_elems) {
187  int i, j;
188  avio_printf(s->pb, ", S=%d", pkt->side_data_elems);
189  for (i = 0; i < pkt->side_data_elems; i++) {
190  av_hash_init(c->hash);
191  if (HAVE_BIGENDIAN && pkt->side_data[i].type == AV_PKT_DATA_PALETTE) {
192  for (j = 0; j < pkt->side_data[i].size; j += sizeof(uint32_t)) {
193  uint32_t data = AV_RL32(pkt->side_data[i].data + j);
194  av_hash_update(c->hash, (uint8_t *)&data, sizeof(uint32_t));
195  }
196  } else
198  snprintf(buf, sizeof(buf) - (AV_HASH_MAX_SIZE * 2 + 1), ", %8d, ", pkt->side_data[i].size);
199  len = strlen(buf);
200  av_hash_final_hex(c->hash, buf + len, sizeof(buf) - len);
201  avio_write(s->pb, buf, strlen(buf));
202  }
203  }
204 
205  avio_printf(s->pb, "\n");
206  avio_flush(s->pb);
207  return 0;
208 }
209 
210 static int framehash_write_trailer(struct AVFormatContext *s)
211 {
212  struct HashContext *c = s->priv_data;
213  av_hash_freep(&c->hash);
214  return 0;
215 }
216 #endif
217 
218 #if CONFIG_FRAMEHASH_MUXER
219 static const AVClass framehash_class = {
220  .class_name = "frame hash muxer",
221  .item_name = av_default_item_name,
222  .option = hash_options,
223  .version = LIBAVUTIL_VERSION_INT,
224 };
225 
227  .name = "framehash",
228  .long_name = NULL_IF_CONFIG_SMALL("Per-frame hash testing"),
229  .priv_data_size = sizeof(struct HashContext),
230  .audio_codec = AV_CODEC_ID_PCM_S16LE,
231  .video_codec = AV_CODEC_ID_RAWVIDEO,
232  .write_header = framehash_write_header,
233  .write_packet = framehash_write_packet,
234  .write_trailer = framehash_write_trailer,
237  .priv_class = &framehash_class,
238 };
239 #endif
240 
241 #if CONFIG_FRAMEMD5_MUXER
242 static const AVClass framemd5_class = {
243  .class_name = "frame MD5 muxer",
244  .item_name = av_default_item_name,
245  .option = md5_options,
246  .version = LIBAVUTIL_VERSION_INT,
247 };
248 
250  .name = "framemd5",
251  .long_name = NULL_IF_CONFIG_SMALL("Per-frame MD5 testing"),
252  .priv_data_size = sizeof(struct HashContext),
253  .audio_codec = AV_CODEC_ID_PCM_S16LE,
254  .video_codec = AV_CODEC_ID_RAWVIDEO,
255  .write_header = framehash_write_header,
256  .write_packet = framehash_write_packet,
257  .write_trailer = framehash_write_trailer,
260  .priv_class = &framemd5_class,
261 };
262 #endif
AV_CODEC_ID_PCM_S16LE
@ AV_CODEC_ID_PCM_S16LE
Definition: avcodec.h:463
AVCodecParameters::extradata
uint8_t * extradata
Extra binary data needed for initializing the decoder, codec-dependent.
Definition: avcodec.h:3971
AVOutputFormat::name
const char * name
Definition: avformat.h:496
opt.h
AV_HASH_MAX_SIZE
#define AV_HASH_MAX_SIZE
Maximum value that av_hash_get_size() will currently return.
Definition: hash.h:157
AVCodecParameters
This struct describes the properties of an encoded stream.
Definition: avcodec.h:3949
AVFMT_VARIABLE_FPS
#define AVFMT_VARIABLE_FPS
Format allows variable fps.
Definition: avformat.h:470
AV_CODEC_ID_RAWVIDEO
@ AV_CODEC_ID_RAWVIDEO
Definition: avcodec.h:231
AVPacket::data
uint8_t * data
Definition: avcodec.h:1477
AVOption
AVOption.
Definition: opt.h:246
AV_PKT_DATA_PALETTE
@ AV_PKT_DATA_PALETTE
An AV_PKT_DATA_PALETTE side data packet contains exactly AVPALETTE_SIZE bytes worth of palette.
Definition: avcodec.h:1190
data
const char data[16]
Definition: mxf.c:91
AVPacket::duration
int64_t duration
Duration of this packet in AVStream->time_base units, 0 if unknown.
Definition: avcodec.h:1495
av_strlcatf
size_t av_strlcatf(char *dst, size_t size, const char *fmt,...)
Definition: avstring.c:101
av_hash_get_name
const char * av_hash_get_name(const AVHashContext *ctx)
Definition: hash.c:90
avassert.h
buf
void * buf
Definition: avisynth_c.h:766
intreadwrite.h
s
#define s(width, name)
Definition: cbs_vp9.c:257
av_hash_alloc
int av_hash_alloc(AVHashContext **ctx, const char *name)
Allocate a hash context for the algorithm specified by name.
Definition: hash.c:100
AVPacketSideData::data
uint8_t * data
Definition: avcodec.h:1421
AVFormatContext
Format I/O context.
Definition: avformat.h:1342
internal.h
HashContext
Definition: hashenc.c:30
AVStream::codecpar
AVCodecParameters * codecpar
Codec parameters associated with this stream.
Definition: avformat.h:1017
LIBAVUTIL_VERSION_INT
#define LIBAVUTIL_VERSION_INT
Definition: version.h:85
AVClass
Describe the class of an AVClass context structure.
Definition: log.h:67
NULL
#define NULL
Definition: coverity.c:32
OFFSET
#define OFFSET(x)
Definition: hashenc.c:37
av_hash_init
void av_hash_init(AVHashContext *ctx)
Initialize or reset a hash context.
Definition: hash.c:137
AVPacketSideData::type
enum AVPacketSideDataType type
Definition: avcodec.h:1423
av_default_item_name
const char * av_default_item_name(void *ptr)
Return the context name.
Definition: log.c:191
c
Undefined Behavior In the C some operations are like signed integer dereferencing freed accessing outside allocated Undefined Behavior must not occur in a C it is not safe even if the output of undefined operations is unused The unsafety may seem nit picking but Optimizing compilers have in fact optimized code on the assumption that no undefined Behavior occurs Optimizing code based on wrong assumptions can and has in some cases lead to effects beyond the output of computations The signed integer overflow problem in speed critical code Code which is highly optimized and works with signed integers sometimes has the problem that often the output of the computation does not c
Definition: undefined.txt:32
av_hash_freep
void av_hash_freep(AVHashContext **ctx)
Free hash context and set hash context pointer to NULL.
Definition: hash.c:238
AVCodecParameters::extradata_size
int extradata_size
Size of the extradata content in bytes.
Definition: avcodec.h:3975
HashContext::hash_name
char * hash_name
Definition: hashenc.c:33
AVPacket::size
int size
Definition: avcodec.h:1478
NULL_IF_CONFIG_SMALL
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition: internal.h:188
AVPacket::dts
int64_t dts
Decompression timestamp in AVStream->time_base units; the time at which the packet is decompressed.
Definition: avcodec.h:1476
avio_write
void avio_write(AVIOContext *s, const unsigned char *buf, int size)
Definition: aviobuf.c:218
AVPacketSideData::size
int size
Definition: avcodec.h:1422
AVHashContext
Definition: hash.c:56
AVOutputFormat
Definition: avformat.h:495
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:259
AVPacket::pts
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
Definition: avcodec.h:1470
uint8_t
uint8_t
Definition: audio_convert.c:194
len
int len
Definition: vorbis_enc_data.h:452
ENC
#define ENC
Definition: hashenc.c:38
AVFMT_TS_NEGATIVE
#define AVFMT_TS_NEGATIVE
Format allows muxing negative timestamps.
Definition: avformat.h:480
AVFMT_TS_NONSTRICT
#define AVFMT_TS_NONSTRICT
Format does not require strictly increasing timestamps, but they must still be monotonic.
Definition: avformat.h:477
AVStream
Stream structure.
Definition: avformat.h:870
AVClass::class_name
const char * class_name
The name of the class; usually it is the same name as the context structure type to which the AVClass...
Definition: log.h:72
avformat.h
ff_framehash_muxer
AVOutputFormat ff_framehash_muxer
AVPacket::side_data
AVPacketSideData * side_data
Additional packet data that can be provided by the container.
Definition: avcodec.h:1488
AV_RL32
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_RL32
Definition: bytestream.h:88
avio_printf
int avio_printf(AVIOContext *s, const char *fmt,...) av_printf_format(2
HashContext::format_version
int format_version
Definition: hashenc.c:34
hash.h
ff_md5_muxer
AVOutputFormat ff_md5_muxer
pkt
static AVPacket pkt
Definition: demuxing_decoding.c:54
AV_OPT_TYPE_INT
@ AV_OPT_TYPE_INT
Definition: opt.h:223
AVPacket::stream_index
int stream_index
Definition: avcodec.h:1479
av_hash_update
void av_hash_update(AVHashContext *ctx, const uint8_t *src, int len)
Update a hash context with additional data.
Definition: hash.c:159
av_hash_final_hex
void av_hash_final_hex(struct AVHashContext *ctx, uint8_t *dst, int size)
Finalize a hash context and store the hexadecimal representation of the actual hash value as a string...
Definition: hash.c:215
avio_flush
int void avio_flush(AVIOContext *s)
Force flushing of buffered data.
Definition: aviobuf.c:238
AVPacket
This structure stores compressed data.
Definition: avcodec.h:1454
ff_framehash_write_header
int ff_framehash_write_header(AVFormatContext *s)
Set the timebase for each stream from the corresponding codec timebase and print it.
Definition: framehash.c:23
HashContext::avclass
const AVClass * avclass
Definition: hashenc.c:31
avstring.h
AV_OPT_TYPE_STRING
@ AV_OPT_TYPE_STRING
Definition: opt.h:227
ff_framemd5_muxer
AVOutputFormat ff_framemd5_muxer
snprintf
#define snprintf
Definition: snprintf.h:34
HashContext::hash
struct AVHashContext * hash
Definition: hashenc.c:32
AVPacket::side_data_elems
int side_data_elems
Definition: avcodec.h:1489
ff_hash_muxer
AVOutputFormat ff_hash_muxer