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 "config_components.h"
23 
24 #include "libavutil/avstring.h"
25 #include "libavutil/hash.h"
26 #include "libavutil/intreadwrite.h"
27 #include "libavutil/mem.h"
28 #include "libavutil/opt.h"
29 #include "avformat.h"
30 #include "internal.h"
31 #include "mux.h"
32 
33 struct HashContext {
34  const AVClass *avclass;
36  char *hash_name;
39 };
40 
41 #define OFFSET(x) offsetof(struct HashContext, x)
42 #define ENC AV_OPT_FLAG_ENCODING_PARAM
43 #define HASH_OPT(defaulttype) \
44  { "hash", "set hash to use", OFFSET(hash_name), AV_OPT_TYPE_STRING, {.str = defaulttype}, 0, 0, ENC }
45 #define FORMAT_VERSION_OPT \
46  { "format_version", "file format version", OFFSET(format_version), AV_OPT_TYPE_INT, {.i64 = 2}, 1, 2, ENC }
47 
48 #if CONFIG_HASH_MUXER || CONFIG_STREAMHASH_MUXER
49 static const AVOption hash_streamhash_options[] = {
50  HASH_OPT("sha256"),
51  { NULL },
52 };
53 
54 static const AVClass hash_streamhashenc_class = {
55  .class_name = "(stream) hash muxer",
56  .item_name = av_default_item_name,
57  .option = hash_streamhash_options,
58  .version = LIBAVUTIL_VERSION_INT,
59 };
60 #endif
61 
62 #if CONFIG_FRAMEHASH_MUXER
63 static const AVOption framehash_options[] = {
64  HASH_OPT("sha256"),
66  { NULL },
67 };
68 #endif
69 
70 #if CONFIG_MD5_MUXER
71 static const AVOption md5_options[] = {
72  HASH_OPT("md5"),
73  { NULL },
74 };
75 #endif
76 
77 #if CONFIG_FRAMEMD5_MUXER
78 static const AVOption framemd5_options[] = {
79  HASH_OPT("md5"),
81  { NULL },
82 };
83 #endif
84 
85 #if CONFIG_HASH_MUXER || CONFIG_MD5_MUXER
86 static int hash_init(struct AVFormatContext *s)
87 {
88  int res;
89  struct HashContext *c = s->priv_data;
90  c->per_stream = 0;
91  c->hashes = av_mallocz(sizeof(*c->hashes));
92  if (!c->hashes)
93  return AVERROR(ENOMEM);
94  res = av_hash_alloc(&c->hashes[0], c->hash_name);
95  if (res < 0)
96  return res;
97  av_hash_init(c->hashes[0]);
98  return 0;
99 }
100 #endif
101 
102 #if CONFIG_STREAMHASH_MUXER
103 static int streamhash_init(struct AVFormatContext *s)
104 {
105  int res, i;
106  struct HashContext *c = s->priv_data;
107  c->per_stream = 1;
108  c->hashes = av_calloc(s->nb_streams, sizeof(*c->hashes));
109  if (!c->hashes)
110  return AVERROR(ENOMEM);
111  for (i = 0; i < s->nb_streams; i++) {
112  res = av_hash_alloc(&c->hashes[i], c->hash_name);
113  if (res < 0) {
114  return res;
115  }
116  av_hash_init(c->hashes[i]);
117  }
118  return 0;
119 }
120 #endif
121 
122 #if CONFIG_HASH_MUXER || CONFIG_MD5_MUXER || CONFIG_STREAMHASH_MUXER
123 static char get_media_type_char(enum AVMediaType type)
124 {
125  switch (type) {
126  case AVMEDIA_TYPE_VIDEO: return 'v';
127  case AVMEDIA_TYPE_AUDIO: return 'a';
128  case AVMEDIA_TYPE_DATA: return 'd';
129  case AVMEDIA_TYPE_SUBTITLE: return 's';
130  case AVMEDIA_TYPE_ATTACHMENT: return 't';
131  default: return '?';
132  }
133 }
134 
135 static int hash_write_packet(struct AVFormatContext *s, AVPacket *pkt)
136 {
137  struct HashContext *c = s->priv_data;
138  av_hash_update(c->hashes[c->per_stream ? pkt->stream_index : 0], pkt->data, pkt->size);
139  return 0;
140 }
141 
142 static int hash_write_trailer(struct AVFormatContext *s)
143 {
144  struct HashContext *c = s->priv_data;
145  int num_hashes = c->per_stream ? s->nb_streams : 1;
146  for (int i = 0; i < num_hashes; i++) {
147  char buf[AV_HASH_MAX_SIZE*2+128];
148  if (c->per_stream) {
149  AVStream *st = s->streams[i];
150  snprintf(buf, sizeof(buf) - 200, "%d,%c,%s=", i, get_media_type_char(st->codecpar->codec_type),
151  av_hash_get_name(c->hashes[i]));
152  } else {
153  snprintf(buf, sizeof(buf) - 200, "%s=", av_hash_get_name(c->hashes[i]));
154  }
155  av_hash_final_hex(c->hashes[i], buf + strlen(buf), sizeof(buf) - strlen(buf));
156  av_strlcatf(buf, sizeof(buf), "\n");
157  avio_write(s->pb, buf, strlen(buf));
158  }
159 
160  return 0;
161 }
162 #endif
163 
164 static void hash_free(struct AVFormatContext *s)
165 {
166  struct HashContext *c = s->priv_data;
167  if (c->hashes) {
168  int num_hashes = c->per_stream ? s->nb_streams : 1;
169  for (int i = 0; i < num_hashes; i++) {
170  av_hash_freep(&c->hashes[i]);
171  }
172  }
173  av_freep(&c->hashes);
174 }
175 
176 #if CONFIG_HASH_MUXER
178  .p.name = "hash",
179  .p.long_name = NULL_IF_CONFIG_SMALL("Hash testing"),
180  .priv_data_size = sizeof(struct HashContext),
181  .p.audio_codec = AV_CODEC_ID_PCM_S16LE,
182  .p.video_codec = AV_CODEC_ID_RAWVIDEO,
183  .init = hash_init,
184  .write_packet = hash_write_packet,
185  .write_trailer = hash_write_trailer,
186  .deinit = hash_free,
189  .p.priv_class = &hash_streamhashenc_class,
190 };
191 #endif
192 
193 #if CONFIG_MD5_MUXER
194 static const AVClass md5enc_class = {
195  .class_name = "MD5 muxer",
196  .item_name = av_default_item_name,
197  .option = md5_options,
198  .version = LIBAVUTIL_VERSION_INT,
199 };
200 
202  .p.name = "md5",
203  .p.long_name = NULL_IF_CONFIG_SMALL("MD5 testing"),
204  .priv_data_size = sizeof(struct HashContext),
205  .p.audio_codec = AV_CODEC_ID_PCM_S16LE,
206  .p.video_codec = AV_CODEC_ID_RAWVIDEO,
207  .init = hash_init,
208  .write_packet = hash_write_packet,
209  .write_trailer = hash_write_trailer,
210  .deinit = hash_free,
213  .p.priv_class = &md5enc_class,
214 };
215 #endif
216 
217 #if CONFIG_STREAMHASH_MUXER
219  .p.name = "streamhash",
220  .p.long_name = NULL_IF_CONFIG_SMALL("Per-stream hash testing"),
221  .priv_data_size = sizeof(struct HashContext),
222  .p.audio_codec = AV_CODEC_ID_PCM_S16LE,
223  .p.video_codec = AV_CODEC_ID_RAWVIDEO,
224  .init = streamhash_init,
225  .write_packet = hash_write_packet,
226  .write_trailer = hash_write_trailer,
227  .deinit = hash_free,
230  .p.priv_class = &hash_streamhashenc_class,
231 };
232 #endif
233 
234 #if CONFIG_FRAMEHASH_MUXER || CONFIG_FRAMEMD5_MUXER
235 static void framehash_print_extradata(struct AVFormatContext *s)
236 {
237  int i;
238 
239  for (i = 0; i < s->nb_streams; i++) {
240  AVStream *st = s->streams[i];
241  AVCodecParameters *par = st->codecpar;
242  if (par->extradata) {
243  struct HashContext *c = s->priv_data;
244  char buf[AV_HASH_MAX_SIZE*2+1];
245 
246  avio_printf(s->pb, "#extradata %d, %31d, ", i, par->extradata_size);
247  av_hash_init(c->hashes[0]);
248  av_hash_update(c->hashes[0], par->extradata, par->extradata_size);
249  av_hash_final_hex(c->hashes[0], buf, sizeof(buf));
250  avio_write(s->pb, buf, strlen(buf));
251  avio_printf(s->pb, "\n");
252  }
253  }
254 }
255 
256 static int framehash_init(struct AVFormatContext *s)
257 {
258  int res;
259  struct HashContext *c = s->priv_data;
260  c->per_stream = 0;
261  c->hashes = av_mallocz(sizeof(*c->hashes));
262  if (!c->hashes)
263  return AVERROR(ENOMEM);
264  res = av_hash_alloc(&c->hashes[0], c->hash_name);
265  if (res < 0)
266  return res;
267  return 0;
268 }
269 
270 static int framehash_write_header(struct AVFormatContext *s)
271 {
272  struct HashContext *c = s->priv_data;
273  avio_printf(s->pb, "#format: frame checksums\n");
274  avio_printf(s->pb, "#version: %d\n", c->format_version);
275  avio_printf(s->pb, "#hash: %s\n", av_hash_get_name(c->hashes[0]));
276  framehash_print_extradata(s);
278  avio_printf(s->pb, "#stream#, dts, pts, duration, size, hash\n");
279  return 0;
280 }
281 
282 static int framehash_write_packet(struct AVFormatContext *s, AVPacket *pkt)
283 {
284  struct HashContext *c = s->priv_data;
285  char buf[AV_HASH_MAX_SIZE*2+128];
286  int len;
287  av_hash_init(c->hashes[0]);
288  av_hash_update(c->hashes[0], pkt->data, pkt->size);
289 
290  snprintf(buf, sizeof(buf) - (AV_HASH_MAX_SIZE * 2 + 1), "%d, %10"PRId64", %10"PRId64", %8"PRId64", %8d, ",
292  len = strlen(buf);
293  av_hash_final_hex(c->hashes[0], buf + len, sizeof(buf) - len);
294  avio_write(s->pb, buf, strlen(buf));
295 
296  if (c->format_version > 1 && pkt->side_data_elems) {
297  int i;
298  avio_printf(s->pb, ", S=%d", pkt->side_data_elems);
299  for (i = 0; i < pkt->side_data_elems; i++) {
300  av_hash_init(c->hashes[0]);
301  if (HAVE_BIGENDIAN && pkt->side_data[i].type == AV_PKT_DATA_PALETTE) {
302  for (size_t j = 0; j < pkt->side_data[i].size; j += sizeof(uint32_t)) {
303  uint32_t data = AV_RL32(pkt->side_data[i].data + j);
304  av_hash_update(c->hashes[0], (uint8_t *)&data, sizeof(uint32_t));
305  }
306  } else
307  av_hash_update(c->hashes[0], pkt->side_data[i].data, pkt->side_data[i].size);
308  snprintf(buf, sizeof(buf) - (AV_HASH_MAX_SIZE * 2 + 1),
309  ", %8"SIZE_SPECIFIER", ", pkt->side_data[i].size);
310  len = strlen(buf);
311  av_hash_final_hex(c->hashes[0], buf + len, sizeof(buf) - len);
312  avio_write(s->pb, buf, strlen(buf));
313  }
314  }
315 
316  avio_printf(s->pb, "\n");
317  return 0;
318 }
319 #endif
320 
321 #if CONFIG_FRAMEHASH_MUXER
322 static const AVClass framehash_class = {
323  .class_name = "frame hash muxer",
324  .item_name = av_default_item_name,
325  .option = framehash_options,
326  .version = LIBAVUTIL_VERSION_INT,
327 };
328 
330  .p.name = "framehash",
331  .p.long_name = NULL_IF_CONFIG_SMALL("Per-frame hash testing"),
332  .priv_data_size = sizeof(struct HashContext),
333  .p.audio_codec = AV_CODEC_ID_PCM_S16LE,
334  .p.video_codec = AV_CODEC_ID_RAWVIDEO,
335  .init = framehash_init,
336  .write_header = framehash_write_header,
337  .write_packet = framehash_write_packet,
338  .deinit = hash_free,
341  .p.priv_class = &framehash_class,
342 };
343 #endif
344 
345 #if CONFIG_FRAMEMD5_MUXER
346 static const AVClass framemd5_class = {
347  .class_name = "frame MD5 muxer",
348  .item_name = av_default_item_name,
349  .option = framemd5_options,
350  .version = LIBAVUTIL_VERSION_INT,
351 };
352 
354  .p.name = "framemd5",
355  .p.long_name = NULL_IF_CONFIG_SMALL("Per-frame MD5 testing"),
356  .priv_data_size = sizeof(struct HashContext),
357  .p.audio_codec = AV_CODEC_ID_PCM_S16LE,
358  .p.video_codec = AV_CODEC_ID_RAWVIDEO,
359  .init = framehash_init,
360  .write_header = framehash_write_header,
361  .write_packet = framehash_write_packet,
362  .deinit = hash_free,
365  .p.priv_class = &framemd5_class,
366 };
367 #endif
AV_CODEC_ID_PCM_S16LE
@ AV_CODEC_ID_PCM_S16LE
Definition: codec_id.h:328
AVMEDIA_TYPE_SUBTITLE
@ AVMEDIA_TYPE_SUBTITLE
Definition: avutil.h:204
AVCodecParameters::extradata
uint8_t * extradata
Extra binary data needed for initializing the decoder, codec-dependent.
Definition: codec_par.h:69
AVOutputFormat::name
const char * name
Definition: avformat.h:510
AVERROR
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
opt.h
AVCodecParameters::codec_type
enum AVMediaType codec_type
General type of the encoded data.
Definition: codec_par.h:51
AV_HASH_MAX_SIZE
#define AV_HASH_MAX_SIZE
Maximum value that av_hash_get_size() will currently return.
Definition: hash.h:156
AVCodecParameters
This struct describes the properties of an encoded stream.
Definition: codec_par.h:47
AVFMT_VARIABLE_FPS
#define AVFMT_VARIABLE_FPS
Format allows variable fps.
Definition: avformat.h:482
AV_CODEC_ID_RAWVIDEO
@ AV_CODEC_ID_RAWVIDEO
Definition: codec_id.h:65
AVPacket::data
uint8_t * data
Definition: packet.h:520
AVOption
AVOption.
Definition: opt.h:357
data
const char data[16]
Definition: mxf.c:148
AVPacket::duration
int64_t duration
Duration of this packet in AVStream->time_base units, 0 if unknown.
Definition: packet.h:538
get_media_type_char
static char get_media_type_char(enum AVMediaType type)
Definition: opt_common.c:654
av_strlcatf
size_t av_strlcatf(char *dst, size_t size, const char *fmt,...)
Definition: avstring.c:103
FFOutputFormat::p
AVOutputFormat p
The public AVOutputFormat.
Definition: mux.h:65
ff_framemd5_muxer
const FFOutputFormat ff_framemd5_muxer
AVPacketSideData::size
size_t size
Definition: packet.h:373
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: packet.h:47
av_hash_get_name
const char * av_hash_get_name(const AVHashContext *ctx)
Definition: hash.c:104
FORMAT_VERSION_OPT
#define FORMAT_VERSION_OPT
Definition: hashenc.c:45
type
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf type
Definition: writing_filters.txt:86
pkt
AVPacket * pkt
Definition: movenc.c:60
hash_free
static void hash_free(struct AVFormatContext *s)
Definition: hashenc.c:164
intreadwrite.h
s
#define s(width, name)
Definition: cbs_vp9.c:198
AVMEDIA_TYPE_AUDIO
@ AVMEDIA_TYPE_AUDIO
Definition: avutil.h:202
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:114
AVPacketSideData::data
uint8_t * data
Definition: packet.h:372
AVMEDIA_TYPE_DATA
@ AVMEDIA_TYPE_DATA
Opaque data information usually continuous.
Definition: avutil.h:203
AVFormatContext
Format I/O context.
Definition: avformat.h:1255
internal.h
HashContext
Definition: hashenc.c:33
AVStream::codecpar
AVCodecParameters * codecpar
Codec parameters associated with this stream.
Definition: avformat.h:766
LIBAVUTIL_VERSION_INT
#define LIBAVUTIL_VERSION_INT
Definition: version.h:85
AVClass
Describe the class of an AVClass context structure.
Definition: log.h:66
NULL
#define NULL
Definition: coverity.c:32
av_hash_init
void av_hash_init(AVHashContext *ctx)
Initialize or reset a hash context.
Definition: hash.c:151
AVPacketSideData::type
enum AVPacketSideDataType type
Definition: packet.h:374
av_default_item_name
const char * av_default_item_name(void *ptr)
Return the context name.
Definition: log.c:237
FFOutputFormat
Definition: mux.h:61
av_hash_update
void av_hash_update(AVHashContext *ctx, const uint8_t *src, size_t len)
Update a hash context with additional data.
Definition: hash.c:172
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:248
AVCodecParameters::extradata_size
int extradata_size
Size of the extradata content in bytes.
Definition: codec_par.h:73
HashContext::hash_name
char * hash_name
Definition: hashenc.c:36
AVMediaType
AVMediaType
Definition: avutil.h:199
AVPacket::size
int size
Definition: packet.h:521
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:94
ff_framehash_muxer
const FFOutputFormat ff_framehash_muxer
ff_streamhash_muxer
const FFOutputFormat ff_streamhash_muxer
AVPacket::dts
int64_t dts
Decompression timestamp in AVStream->time_base units; the time at which the packet is decompressed.
Definition: packet.h:519
avio_write
void avio_write(AVIOContext *s, const unsigned char *buf, int size)
Definition: aviobuf.c:201
AVHashContext
Definition: hash.c:66
HashContext::hashes
struct AVHashContext ** hashes
Definition: hashenc.c:35
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:256
AVPacket::pts
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
Definition: packet.h:513
ff_hash_muxer
const FFOutputFormat ff_hash_muxer
AVMEDIA_TYPE_ATTACHMENT
@ AVMEDIA_TYPE_ATTACHMENT
Opaque data information usually sparse.
Definition: avutil.h:205
av_mallocz
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
Definition: mem.c:256
len
int len
Definition: vorbis_enc_data.h:426
av_calloc
void * av_calloc(size_t nmemb, size_t size)
Definition: mem.c:264
AVFMT_TS_NEGATIVE
#define AVFMT_TS_NEGATIVE
Format allows muxing negative timestamps.
Definition: avformat.h:494
AVFMT_TS_NONSTRICT
#define AVFMT_TS_NONSTRICT
Format does not require strictly increasing timestamps, but they must still be monotonic.
Definition: avformat.h:491
AVStream
Stream structure.
Definition: avformat.h:743
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:71
avformat.h
AVPacket::side_data
AVPacketSideData * side_data
Additional packet data that can be provided by the container.
Definition: packet.h:531
AV_RL32
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_RL32
Definition: bytestream.h:92
SIZE_SPECIFIER
#define SIZE_SPECIFIER
Definition: internal.h:129
avio_printf
int avio_printf(AVIOContext *s, const char *fmt,...) av_printf_format(2
Writes a formatted string to the context.
HashContext::format_version
int format_version
Definition: hashenc.c:38
ff_md5_muxer
const FFOutputFormat ff_md5_muxer
hash.h
HashContext::per_stream
int per_stream
Definition: hashenc.c:37
AVPacket::stream_index
int stream_index
Definition: packet.h:522
AVMEDIA_TYPE_VIDEO
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:201
mem.h
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:225
HASH_OPT
#define HASH_OPT(defaulttype)
Definition: hashenc.c:43
AVPacket
This structure stores compressed data.
Definition: packet.h:497
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:34
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:25
HashContext::avclass
const AVClass * avclass
Definition: hashenc.c:34
avstring.h
snprintf
#define snprintf
Definition: snprintf.h:34
AVPacket::side_data_elems
int side_data_elems
Definition: packet.h:532
mux.h