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;
36 };
37 
38 #define OFFSET(x) offsetof(struct HashContext, x)
39 #define ENC AV_OPT_FLAG_ENCODING_PARAM
40 #define HASH_OPT(defaulttype) \
41  { "hash", "set hash to use", OFFSET(hash_name), AV_OPT_TYPE_STRING, {.str = defaulttype}, 0, 0, ENC }
42 #define FORMAT_VERSION_OPT \
43  { "format_version", "file format version", OFFSET(format_version), AV_OPT_TYPE_INT, {.i64 = 2}, 1, 2, ENC }
44 
45 #if CONFIG_HASH_MUXER
46 static const AVOption hash_options[] = {
47  HASH_OPT("sha256"),
48  { NULL },
49 };
50 #endif
51 
52 #if CONFIG_FRAMEHASH_MUXER
53 static const AVOption framehash_options[] = {
54  HASH_OPT("sha256"),
56  { NULL },
57 };
58 #endif
59 
60 #if CONFIG_STREAMHASH_MUXER
61 static const AVOption streamhash_options[] = {
62  HASH_OPT("sha256"),
63  { NULL },
64 };
65 #endif
66 
67 #if CONFIG_MD5_MUXER
68 static const AVOption md5_options[] = {
69  HASH_OPT("md5"),
70  { NULL },
71 };
72 #endif
73 
74 #if CONFIG_FRAMEMD5_MUXER
75 static const AVOption framemd5_options[] = {
76  HASH_OPT("md5"),
78  { NULL },
79 };
80 #endif
81 
82 #if CONFIG_HASH_MUXER || CONFIG_MD5_MUXER
83 static int hash_init(struct AVFormatContext *s)
84 {
85  int res;
86  struct HashContext *c = s->priv_data;
87  c->per_stream = 0;
88  c->hashes = av_mallocz_array(1, sizeof(*c->hashes));
89  if (!c->hashes)
90  return AVERROR(ENOMEM);
91  res = av_hash_alloc(&c->hashes[0], c->hash_name);
92  if (res < 0)
93  return res;
94  av_hash_init(c->hashes[0]);
95  return 0;
96 }
97 #endif
98 
99 #if CONFIG_STREAMHASH_MUXER
100 static int streamhash_init(struct AVFormatContext *s)
101 {
102  int res, i;
103  struct HashContext *c = s->priv_data;
104  c->per_stream = 1;
105  c->hashes = av_mallocz_array(s->nb_streams, sizeof(*c->hashes));
106  if (!c->hashes)
107  return AVERROR(ENOMEM);
108  for (i = 0; i < s->nb_streams; i++) {
109  res = av_hash_alloc(&c->hashes[i], c->hash_name);
110  if (res < 0) {
111  return res;
112  }
113  av_hash_init(c->hashes[i]);
114  }
115  return 0;
116 }
117 #endif
118 
119 #if CONFIG_HASH_MUXER || CONFIG_MD5_MUXER || CONFIG_STREAMHASH_MUXER
120 static char get_media_type_char(enum AVMediaType type)
121 {
122  switch (type) {
123  case AVMEDIA_TYPE_VIDEO: return 'v';
124  case AVMEDIA_TYPE_AUDIO: return 'a';
125  case AVMEDIA_TYPE_DATA: return 'd';
126  case AVMEDIA_TYPE_SUBTITLE: return 's';
127  case AVMEDIA_TYPE_ATTACHMENT: return 't';
128  default: return '?';
129  }
130 }
131 
132 static int hash_write_packet(struct AVFormatContext *s, AVPacket *pkt)
133 {
134  struct HashContext *c = s->priv_data;
135  av_hash_update(c->hashes[c->per_stream ? pkt->stream_index : 0], pkt->data, pkt->size);
136  return 0;
137 }
138 
139 static int hash_write_trailer(struct AVFormatContext *s)
140 {
141  struct HashContext *c = s->priv_data;
142  int num_hashes = c->per_stream ? s->nb_streams : 1;
143  for (int i = 0; i < num_hashes; i++) {
144  char buf[AV_HASH_MAX_SIZE*2+128];
145  if (c->per_stream) {
146  AVStream *st = s->streams[i];
147  snprintf(buf, sizeof(buf) - 200, "%d,%c,%s=", i, get_media_type_char(st->codecpar->codec_type),
148  av_hash_get_name(c->hashes[i]));
149  } else {
150  snprintf(buf, sizeof(buf) - 200, "%s=", av_hash_get_name(c->hashes[i]));
151  }
152  av_hash_final_hex(c->hashes[i], buf + strlen(buf), sizeof(buf) - strlen(buf));
153  av_strlcatf(buf, sizeof(buf), "\n");
154  avio_write(s->pb, buf, strlen(buf));
155  avio_flush(s->pb);
156  }
157 
158  return 0;
159 }
160 
161 static void hash_free(struct AVFormatContext *s)
162 {
163  struct HashContext *c = s->priv_data;
164  if (c->hashes) {
165  int num_hashes = c->per_stream ? s->nb_streams : 1;
166  for (int i = 0; i < num_hashes; i++) {
167  av_hash_freep(&c->hashes[i]);
168  }
169  }
170  av_freep(&c->hashes);
171 }
172 #endif
173 
174 #if CONFIG_HASH_MUXER
175 static const AVClass hashenc_class = {
176  .class_name = "hash muxer",
177  .item_name = av_default_item_name,
178  .option = hash_options,
179  .version = LIBAVUTIL_VERSION_INT,
180 };
181 
183  .name = "hash",
184  .long_name = NULL_IF_CONFIG_SMALL("Hash testing"),
185  .priv_data_size = sizeof(struct HashContext),
186  .audio_codec = AV_CODEC_ID_PCM_S16LE,
187  .video_codec = AV_CODEC_ID_RAWVIDEO,
188  .init = hash_init,
189  .write_packet = hash_write_packet,
190  .write_trailer = hash_write_trailer,
191  .deinit = hash_free,
194  .priv_class = &hashenc_class,
195 };
196 #endif
197 
198 #if CONFIG_MD5_MUXER
199 static const AVClass md5enc_class = {
200  .class_name = "MD5 muxer",
201  .item_name = av_default_item_name,
202  .option = md5_options,
203  .version = LIBAVUTIL_VERSION_INT,
204 };
205 
207  .name = "md5",
208  .long_name = NULL_IF_CONFIG_SMALL("MD5 testing"),
209  .priv_data_size = sizeof(struct HashContext),
210  .audio_codec = AV_CODEC_ID_PCM_S16LE,
211  .video_codec = AV_CODEC_ID_RAWVIDEO,
212  .init = hash_init,
213  .write_packet = hash_write_packet,
214  .write_trailer = hash_write_trailer,
215  .deinit = hash_free,
218  .priv_class = &md5enc_class,
219 };
220 #endif
221 
222 #if CONFIG_STREAMHASH_MUXER
223 static const AVClass streamhashenc_class = {
224  .class_name = "stream hash muxer",
225  .item_name = av_default_item_name,
226  .option = streamhash_options,
227  .version = LIBAVUTIL_VERSION_INT,
228 };
229 
231  .name = "streamhash",
232  .long_name = NULL_IF_CONFIG_SMALL("Per-stream hash testing"),
233  .priv_data_size = sizeof(struct HashContext),
234  .audio_codec = AV_CODEC_ID_PCM_S16LE,
235  .video_codec = AV_CODEC_ID_RAWVIDEO,
236  .init = streamhash_init,
237  .write_packet = hash_write_packet,
238  .write_trailer = hash_write_trailer,
239  .deinit = hash_free,
242  .priv_class = &streamhashenc_class,
243 };
244 #endif
245 
246 #if CONFIG_FRAMEHASH_MUXER || CONFIG_FRAMEMD5_MUXER
247 static void framehash_print_extradata(struct AVFormatContext *s)
248 {
249  int i;
250 
251  for (i = 0; i < s->nb_streams; i++) {
252  AVStream *st = s->streams[i];
253  AVCodecParameters *par = st->codecpar;
254  if (par->extradata) {
255  struct HashContext *c = s->priv_data;
256  char buf[AV_HASH_MAX_SIZE*2+1];
257 
258  avio_printf(s->pb, "#extradata %d, %31d, ", i, par->extradata_size);
259  av_hash_init(c->hashes[0]);
260  av_hash_update(c->hashes[0], par->extradata, par->extradata_size);
261  av_hash_final_hex(c->hashes[0], buf, sizeof(buf));
262  avio_write(s->pb, buf, strlen(buf));
263  avio_printf(s->pb, "\n");
264  }
265  }
266 }
267 
268 static int framehash_init(struct AVFormatContext *s)
269 {
270  int res;
271  struct HashContext *c = s->priv_data;
272  c->per_stream = 0;
273  c->hashes = av_mallocz_array(1, sizeof(*c->hashes));
274  if (!c->hashes)
275  return AVERROR(ENOMEM);
276  res = av_hash_alloc(&c->hashes[0], c->hash_name);
277  if (res < 0)
278  return res;
279  return 0;
280 }
281 
282 static int framehash_write_header(struct AVFormatContext *s)
283 {
284  struct HashContext *c = s->priv_data;
285  avio_printf(s->pb, "#format: frame checksums\n");
286  avio_printf(s->pb, "#version: %d\n", c->format_version);
287  avio_printf(s->pb, "#hash: %s\n", av_hash_get_name(c->hashes[0]));
288  framehash_print_extradata(s);
290  avio_printf(s->pb, "#stream#, dts, pts, duration, size, hash\n");
291  return 0;
292 }
293 
294 static int framehash_write_packet(struct AVFormatContext *s, AVPacket *pkt)
295 {
296  struct HashContext *c = s->priv_data;
297  char buf[AV_HASH_MAX_SIZE*2+128];
298  int len;
299  av_hash_init(c->hashes[0]);
300  av_hash_update(c->hashes[0], pkt->data, pkt->size);
301 
302  snprintf(buf, sizeof(buf) - (AV_HASH_MAX_SIZE * 2 + 1), "%d, %10"PRId64", %10"PRId64", %8"PRId64", %8d, ",
303  pkt->stream_index, pkt->dts, pkt->pts, pkt->duration, pkt->size);
304  len = strlen(buf);
305  av_hash_final_hex(c->hashes[0], buf + len, sizeof(buf) - len);
306  avio_write(s->pb, buf, strlen(buf));
307 
308  if (c->format_version > 1 && pkt->side_data_elems) {
309  int i, j;
310  avio_printf(s->pb, ", S=%d", pkt->side_data_elems);
311  for (i = 0; i < pkt->side_data_elems; i++) {
312  av_hash_init(c->hashes[0]);
313  if (HAVE_BIGENDIAN && pkt->side_data[i].type == AV_PKT_DATA_PALETTE) {
314  for (j = 0; j < pkt->side_data[i].size; j += sizeof(uint32_t)) {
315  uint32_t data = AV_RL32(pkt->side_data[i].data + j);
316  av_hash_update(c->hashes[0], (uint8_t *)&data, sizeof(uint32_t));
317  }
318  } else
319  av_hash_update(c->hashes[0], pkt->side_data[i].data, pkt->side_data[i].size);
320  snprintf(buf, sizeof(buf) - (AV_HASH_MAX_SIZE * 2 + 1), ", %8d, ", pkt->side_data[i].size);
321  len = strlen(buf);
322  av_hash_final_hex(c->hashes[0], buf + len, sizeof(buf) - len);
323  avio_write(s->pb, buf, strlen(buf));
324  }
325  }
326 
327  avio_printf(s->pb, "\n");
328  avio_flush(s->pb);
329  return 0;
330 }
331 
332 static void framehash_free(struct AVFormatContext *s)
333 {
334  struct HashContext *c = s->priv_data;
335  if (c->hashes)
336  av_hash_freep(&c->hashes[0]);
337  av_freep(&c->hashes);
338 }
339 #endif
340 
341 #if CONFIG_FRAMEHASH_MUXER
342 static const AVClass framehash_class = {
343  .class_name = "frame hash muxer",
344  .item_name = av_default_item_name,
345  .option = framehash_options,
346  .version = LIBAVUTIL_VERSION_INT,
347 };
348 
350  .name = "framehash",
351  .long_name = NULL_IF_CONFIG_SMALL("Per-frame hash testing"),
352  .priv_data_size = sizeof(struct HashContext),
353  .audio_codec = AV_CODEC_ID_PCM_S16LE,
354  .video_codec = AV_CODEC_ID_RAWVIDEO,
355  .init = framehash_init,
356  .write_header = framehash_write_header,
357  .write_packet = framehash_write_packet,
358  .deinit = framehash_free,
361  .priv_class = &framehash_class,
362 };
363 #endif
364 
365 #if CONFIG_FRAMEMD5_MUXER
366 static const AVClass framemd5_class = {
367  .class_name = "frame MD5 muxer",
368  .item_name = av_default_item_name,
369  .option = framemd5_options,
370  .version = LIBAVUTIL_VERSION_INT,
371 };
372 
374  .name = "framemd5",
375  .long_name = NULL_IF_CONFIG_SMALL("Per-frame MD5 testing"),
376  .priv_data_size = sizeof(struct HashContext),
377  .audio_codec = AV_CODEC_ID_PCM_S16LE,
378  .video_codec = AV_CODEC_ID_RAWVIDEO,
379  .init = framehash_init,
380  .write_header = framehash_write_header,
381  .write_packet = framehash_write_packet,
382  .deinit = framehash_free,
385  .priv_class = &framemd5_class,
386 };
387 #endif
#define NULL
Definition: coverity.c:32
AVOption.
Definition: opt.h:246
ptrdiff_t const GLvoid * data
Definition: opengl_enc.c:100
#define LIBAVUTIL_VERSION_INT
Definition: version.h:85
const AVClass * avclass
Definition: hashenc.c:31
AVOutputFormat ff_md5_muxer
int size
Definition: avcodec.h:1481
const char * av_default_item_name(void *ptr)
Return the context name.
Definition: log.c:191
GLint GLenum type
Definition: opengl_enc.c:104
static AVPacket pkt
#define AVFMT_TS_NONSTRICT
Format does not require strictly increasing timestamps, but they must still be monotonic.
Definition: avformat.h:477
This struct describes the properties of an encoded stream.
Definition: avcodec.h:3960
Format I/O context.
Definition: avformat.h:1358
#define AV_HASH_MAX_SIZE
Maximum value that av_hash_get_size() will currently return.
Definition: hash.h:157
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
struct AVHashContext ** hashes
Definition: hashenc.c:32
uint8_t
Opaque data information usually continuous.
Definition: avutil.h:203
Generic hashing API.
AVOutputFormat ff_streamhash_muxer
AVOptions.
int64_t duration
Duration of this packet in AVStream->time_base units, 0 if unknown.
Definition: avcodec.h:1498
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
int format_version
Definition: hashenc.c:35
AVStream ** streams
A list of all streams in the file.
Definition: avformat.h:1426
uint8_t * data
Definition: avcodec.h:1480
uint8_t * data
Definition: avcodec.h:1424
int per_stream
Definition: hashenc.c:34
#define FORMAT_VERSION_OPT
Definition: hashenc.c:42
void avio_write(AVIOContext *s, const unsigned char *buf, int size)
Definition: aviobuf.c:218
void av_hash_init(AVHashContext *ctx)
Initialize or reset a hash context.
Definition: hash.c:137
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:259
An AV_PKT_DATA_PALETTE side data packet contains exactly AVPALETTE_SIZE bytes worth of palette...
Definition: avcodec.h:1193
AVOutputFormat ff_framehash_muxer
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:186
enum AVMediaType codec_type
General type of the encoded data.
Definition: avcodec.h:3964
simple assert() macros that are a bit more flexible than ISO C assert().
enum AVPacketSideDataType type
Definition: avcodec.h:1426
int side_data_elems
Definition: avcodec.h:1492
int av_hash_alloc(AVHashContext **ctx, const char *name)
Allocate a hash context for the algorithm specified by name.
Definition: hash.c:100
int extradata_size
Size of the extradata content in bytes.
Definition: avcodec.h:3986
unsigned int nb_streams
Number of elements in AVFormatContext.streams.
Definition: avformat.h:1414
const char * name
Definition: avformat.h:505
const char * av_hash_get_name(const AVHashContext *ctx)
Definition: hash.c:90
#define s(width, name)
Definition: cbs_vp9.c:257
Opaque data information usually sparse.
Definition: avutil.h:205
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
Stream structure.
Definition: avformat.h:881
static char get_media_type_char(enum AVMediaType type)
Definition: cmdutils.c:1491
AVIOContext * pb
I/O context.
Definition: avformat.h:1400
void av_hash_update(AVHashContext *ctx, const uint8_t *src, int len)
Update a hash context with additional data.
Definition: hash.c:159
void * buf
Definition: avisynth_c.h:766
Describe the class of an AVClass context structure.
Definition: log.h:67
void av_hash_freep(AVHashContext **ctx)
Free hash context and set hash context pointer to NULL.
Definition: hash.c:238
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
AVOutputFormat ff_framemd5_muxer
void avio_flush(AVIOContext *s)
Force flushing of buffered data.
Definition: aviobuf.c:238
AVMediaType
Definition: avutil.h:199
size_t av_strlcatf(char *dst, size_t size, const char *fmt,...)
Definition: avstring.c:101
#define snprintf
Definition: snprintf.h:34
AVOutputFormat ff_hash_muxer
Main libavformat public API header.
AVPacketSideData * side_data
Additional packet data that can be provided by the container.
Definition: avcodec.h:1491
char * hash_name
Definition: hashenc.c:33
#define AVFMT_VARIABLE_FPS
Format allows variable fps.
Definition: avformat.h:470
int len
void * priv_data
Format private data.
Definition: avformat.h:1386
uint8_t * extradata
Extra binary data needed for initializing the decoder, codec-dependent.
Definition: avcodec.h:3982
int64_t dts
Decompression timestamp in AVStream->time_base units; the time at which the packet is decompressed...
Definition: avcodec.h:1479
#define av_freep(p)
AVCodecParameters * codecpar
Codec parameters associated with this stream.
Definition: avformat.h:1028
#define HASH_OPT(defaulttype)
Definition: hashenc.c:40
int stream_index
Definition: avcodec.h:1482
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later.That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another.Frame references ownership and permissions
#define AVFMT_TS_NEGATIVE
Format allows muxing negative timestamps.
Definition: avformat.h:482
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_RL32
Definition: bytestream.h:87
This structure stores compressed data.
Definition: avcodec.h:1457
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
Definition: avcodec.h:1473
int avio_printf(AVIOContext *s, const char *fmt,...) av_printf_format(2
Writes a formatted string to the context.
void * av_mallocz_array(size_t nmemb, size_t size)
Definition: mem.c:191