1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * Hash/MD5 encoder (for codec/format testing) 3cabdff1aSopenharmony_ci * Copyright (c) 2009 Reimar Döffinger, based on crcenc (c) 2002 Fabrice Bellard 4cabdff1aSopenharmony_ci * 5cabdff1aSopenharmony_ci * This file is part of FFmpeg. 6cabdff1aSopenharmony_ci * 7cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or 8cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 9cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either 10cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 11cabdff1aSopenharmony_ci * 12cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 13cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 14cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15cabdff1aSopenharmony_ci * Lesser General Public License for more details. 16cabdff1aSopenharmony_ci * 17cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 18cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software 19cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20cabdff1aSopenharmony_ci */ 21cabdff1aSopenharmony_ci 22cabdff1aSopenharmony_ci#include "config_components.h" 23cabdff1aSopenharmony_ci 24cabdff1aSopenharmony_ci#include "libavutil/avstring.h" 25cabdff1aSopenharmony_ci#include "libavutil/hash.h" 26cabdff1aSopenharmony_ci#include "libavutil/intreadwrite.h" 27cabdff1aSopenharmony_ci#include "libavutil/opt.h" 28cabdff1aSopenharmony_ci#include "avformat.h" 29cabdff1aSopenharmony_ci#include "internal.h" 30cabdff1aSopenharmony_ci 31cabdff1aSopenharmony_cistruct HashContext { 32cabdff1aSopenharmony_ci const AVClass *avclass; 33cabdff1aSopenharmony_ci struct AVHashContext **hashes; 34cabdff1aSopenharmony_ci char *hash_name; 35cabdff1aSopenharmony_ci int per_stream; 36cabdff1aSopenharmony_ci int format_version; 37cabdff1aSopenharmony_ci}; 38cabdff1aSopenharmony_ci 39cabdff1aSopenharmony_ci#define OFFSET(x) offsetof(struct HashContext, x) 40cabdff1aSopenharmony_ci#define ENC AV_OPT_FLAG_ENCODING_PARAM 41cabdff1aSopenharmony_ci#define HASH_OPT(defaulttype) \ 42cabdff1aSopenharmony_ci { "hash", "set hash to use", OFFSET(hash_name), AV_OPT_TYPE_STRING, {.str = defaulttype}, 0, 0, ENC } 43cabdff1aSopenharmony_ci#define FORMAT_VERSION_OPT \ 44cabdff1aSopenharmony_ci { "format_version", "file format version", OFFSET(format_version), AV_OPT_TYPE_INT, {.i64 = 2}, 1, 2, ENC } 45cabdff1aSopenharmony_ci 46cabdff1aSopenharmony_ci#if CONFIG_HASH_MUXER || CONFIG_STREAMHASH_MUXER 47cabdff1aSopenharmony_cistatic const AVOption hash_streamhash_options[] = { 48cabdff1aSopenharmony_ci HASH_OPT("sha256"), 49cabdff1aSopenharmony_ci { NULL }, 50cabdff1aSopenharmony_ci}; 51cabdff1aSopenharmony_ci 52cabdff1aSopenharmony_cistatic const AVClass hash_streamhashenc_class = { 53cabdff1aSopenharmony_ci .class_name = "(stream) hash muxer", 54cabdff1aSopenharmony_ci .item_name = av_default_item_name, 55cabdff1aSopenharmony_ci .option = hash_streamhash_options, 56cabdff1aSopenharmony_ci .version = LIBAVUTIL_VERSION_INT, 57cabdff1aSopenharmony_ci}; 58cabdff1aSopenharmony_ci#endif 59cabdff1aSopenharmony_ci 60cabdff1aSopenharmony_ci#if CONFIG_FRAMEHASH_MUXER 61cabdff1aSopenharmony_cistatic const AVOption framehash_options[] = { 62cabdff1aSopenharmony_ci HASH_OPT("sha256"), 63cabdff1aSopenharmony_ci FORMAT_VERSION_OPT, 64cabdff1aSopenharmony_ci { NULL }, 65cabdff1aSopenharmony_ci}; 66cabdff1aSopenharmony_ci#endif 67cabdff1aSopenharmony_ci 68cabdff1aSopenharmony_ci#if CONFIG_MD5_MUXER 69cabdff1aSopenharmony_cistatic const AVOption md5_options[] = { 70cabdff1aSopenharmony_ci HASH_OPT("md5"), 71cabdff1aSopenharmony_ci { NULL }, 72cabdff1aSopenharmony_ci}; 73cabdff1aSopenharmony_ci#endif 74cabdff1aSopenharmony_ci 75cabdff1aSopenharmony_ci#if CONFIG_FRAMEMD5_MUXER 76cabdff1aSopenharmony_cistatic const AVOption framemd5_options[] = { 77cabdff1aSopenharmony_ci HASH_OPT("md5"), 78cabdff1aSopenharmony_ci FORMAT_VERSION_OPT, 79cabdff1aSopenharmony_ci { NULL }, 80cabdff1aSopenharmony_ci}; 81cabdff1aSopenharmony_ci#endif 82cabdff1aSopenharmony_ci 83cabdff1aSopenharmony_ci#if CONFIG_HASH_MUXER || CONFIG_MD5_MUXER 84cabdff1aSopenharmony_cistatic int hash_init(struct AVFormatContext *s) 85cabdff1aSopenharmony_ci{ 86cabdff1aSopenharmony_ci int res; 87cabdff1aSopenharmony_ci struct HashContext *c = s->priv_data; 88cabdff1aSopenharmony_ci c->per_stream = 0; 89cabdff1aSopenharmony_ci c->hashes = av_mallocz(sizeof(*c->hashes)); 90cabdff1aSopenharmony_ci if (!c->hashes) 91cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 92cabdff1aSopenharmony_ci res = av_hash_alloc(&c->hashes[0], c->hash_name); 93cabdff1aSopenharmony_ci if (res < 0) 94cabdff1aSopenharmony_ci return res; 95cabdff1aSopenharmony_ci av_hash_init(c->hashes[0]); 96cabdff1aSopenharmony_ci return 0; 97cabdff1aSopenharmony_ci} 98cabdff1aSopenharmony_ci#endif 99cabdff1aSopenharmony_ci 100cabdff1aSopenharmony_ci#if CONFIG_STREAMHASH_MUXER 101cabdff1aSopenharmony_cistatic int streamhash_init(struct AVFormatContext *s) 102cabdff1aSopenharmony_ci{ 103cabdff1aSopenharmony_ci int res, i; 104cabdff1aSopenharmony_ci struct HashContext *c = s->priv_data; 105cabdff1aSopenharmony_ci c->per_stream = 1; 106cabdff1aSopenharmony_ci c->hashes = av_calloc(s->nb_streams, sizeof(*c->hashes)); 107cabdff1aSopenharmony_ci if (!c->hashes) 108cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 109cabdff1aSopenharmony_ci for (i = 0; i < s->nb_streams; i++) { 110cabdff1aSopenharmony_ci res = av_hash_alloc(&c->hashes[i], c->hash_name); 111cabdff1aSopenharmony_ci if (res < 0) { 112cabdff1aSopenharmony_ci return res; 113cabdff1aSopenharmony_ci } 114cabdff1aSopenharmony_ci av_hash_init(c->hashes[i]); 115cabdff1aSopenharmony_ci } 116cabdff1aSopenharmony_ci return 0; 117cabdff1aSopenharmony_ci} 118cabdff1aSopenharmony_ci#endif 119cabdff1aSopenharmony_ci 120cabdff1aSopenharmony_ci#if CONFIG_HASH_MUXER || CONFIG_MD5_MUXER || CONFIG_STREAMHASH_MUXER 121cabdff1aSopenharmony_cistatic char get_media_type_char(enum AVMediaType type) 122cabdff1aSopenharmony_ci{ 123cabdff1aSopenharmony_ci switch (type) { 124cabdff1aSopenharmony_ci case AVMEDIA_TYPE_VIDEO: return 'v'; 125cabdff1aSopenharmony_ci case AVMEDIA_TYPE_AUDIO: return 'a'; 126cabdff1aSopenharmony_ci case AVMEDIA_TYPE_DATA: return 'd'; 127cabdff1aSopenharmony_ci case AVMEDIA_TYPE_SUBTITLE: return 's'; 128cabdff1aSopenharmony_ci case AVMEDIA_TYPE_ATTACHMENT: return 't'; 129cabdff1aSopenharmony_ci default: return '?'; 130cabdff1aSopenharmony_ci } 131cabdff1aSopenharmony_ci} 132cabdff1aSopenharmony_ci 133cabdff1aSopenharmony_cistatic int hash_write_packet(struct AVFormatContext *s, AVPacket *pkt) 134cabdff1aSopenharmony_ci{ 135cabdff1aSopenharmony_ci struct HashContext *c = s->priv_data; 136cabdff1aSopenharmony_ci av_hash_update(c->hashes[c->per_stream ? pkt->stream_index : 0], pkt->data, pkt->size); 137cabdff1aSopenharmony_ci return 0; 138cabdff1aSopenharmony_ci} 139cabdff1aSopenharmony_ci 140cabdff1aSopenharmony_cistatic int hash_write_trailer(struct AVFormatContext *s) 141cabdff1aSopenharmony_ci{ 142cabdff1aSopenharmony_ci struct HashContext *c = s->priv_data; 143cabdff1aSopenharmony_ci int num_hashes = c->per_stream ? s->nb_streams : 1; 144cabdff1aSopenharmony_ci for (int i = 0; i < num_hashes; i++) { 145cabdff1aSopenharmony_ci char buf[AV_HASH_MAX_SIZE*2+128]; 146cabdff1aSopenharmony_ci if (c->per_stream) { 147cabdff1aSopenharmony_ci AVStream *st = s->streams[i]; 148cabdff1aSopenharmony_ci snprintf(buf, sizeof(buf) - 200, "%d,%c,%s=", i, get_media_type_char(st->codecpar->codec_type), 149cabdff1aSopenharmony_ci av_hash_get_name(c->hashes[i])); 150cabdff1aSopenharmony_ci } else { 151cabdff1aSopenharmony_ci snprintf(buf, sizeof(buf) - 200, "%s=", av_hash_get_name(c->hashes[i])); 152cabdff1aSopenharmony_ci } 153cabdff1aSopenharmony_ci av_hash_final_hex(c->hashes[i], buf + strlen(buf), sizeof(buf) - strlen(buf)); 154cabdff1aSopenharmony_ci av_strlcatf(buf, sizeof(buf), "\n"); 155cabdff1aSopenharmony_ci avio_write(s->pb, buf, strlen(buf)); 156cabdff1aSopenharmony_ci } 157cabdff1aSopenharmony_ci 158cabdff1aSopenharmony_ci return 0; 159cabdff1aSopenharmony_ci} 160cabdff1aSopenharmony_ci#endif 161cabdff1aSopenharmony_ci 162cabdff1aSopenharmony_cistatic void hash_free(struct AVFormatContext *s) 163cabdff1aSopenharmony_ci{ 164cabdff1aSopenharmony_ci struct HashContext *c = s->priv_data; 165cabdff1aSopenharmony_ci if (c->hashes) { 166cabdff1aSopenharmony_ci int num_hashes = c->per_stream ? s->nb_streams : 1; 167cabdff1aSopenharmony_ci for (int i = 0; i < num_hashes; i++) { 168cabdff1aSopenharmony_ci av_hash_freep(&c->hashes[i]); 169cabdff1aSopenharmony_ci } 170cabdff1aSopenharmony_ci } 171cabdff1aSopenharmony_ci av_freep(&c->hashes); 172cabdff1aSopenharmony_ci} 173cabdff1aSopenharmony_ci 174cabdff1aSopenharmony_ci#if CONFIG_HASH_MUXER 175cabdff1aSopenharmony_ciconst AVOutputFormat ff_hash_muxer = { 176cabdff1aSopenharmony_ci .name = "hash", 177cabdff1aSopenharmony_ci .long_name = NULL_IF_CONFIG_SMALL("Hash testing"), 178cabdff1aSopenharmony_ci .priv_data_size = sizeof(struct HashContext), 179cabdff1aSopenharmony_ci .audio_codec = AV_CODEC_ID_PCM_S16LE, 180cabdff1aSopenharmony_ci .video_codec = AV_CODEC_ID_RAWVIDEO, 181cabdff1aSopenharmony_ci .init = hash_init, 182cabdff1aSopenharmony_ci .write_packet = hash_write_packet, 183cabdff1aSopenharmony_ci .write_trailer = hash_write_trailer, 184cabdff1aSopenharmony_ci .deinit = hash_free, 185cabdff1aSopenharmony_ci .flags = AVFMT_VARIABLE_FPS | AVFMT_TS_NONSTRICT | 186cabdff1aSopenharmony_ci AVFMT_TS_NEGATIVE, 187cabdff1aSopenharmony_ci .priv_class = &hash_streamhashenc_class, 188cabdff1aSopenharmony_ci}; 189cabdff1aSopenharmony_ci#endif 190cabdff1aSopenharmony_ci 191cabdff1aSopenharmony_ci#if CONFIG_MD5_MUXER 192cabdff1aSopenharmony_cistatic const AVClass md5enc_class = { 193cabdff1aSopenharmony_ci .class_name = "MD5 muxer", 194cabdff1aSopenharmony_ci .item_name = av_default_item_name, 195cabdff1aSopenharmony_ci .option = md5_options, 196cabdff1aSopenharmony_ci .version = LIBAVUTIL_VERSION_INT, 197cabdff1aSopenharmony_ci}; 198cabdff1aSopenharmony_ci 199cabdff1aSopenharmony_ciconst AVOutputFormat ff_md5_muxer = { 200cabdff1aSopenharmony_ci .name = "md5", 201cabdff1aSopenharmony_ci .long_name = NULL_IF_CONFIG_SMALL("MD5 testing"), 202cabdff1aSopenharmony_ci .priv_data_size = sizeof(struct HashContext), 203cabdff1aSopenharmony_ci .audio_codec = AV_CODEC_ID_PCM_S16LE, 204cabdff1aSopenharmony_ci .video_codec = AV_CODEC_ID_RAWVIDEO, 205cabdff1aSopenharmony_ci .init = hash_init, 206cabdff1aSopenharmony_ci .write_packet = hash_write_packet, 207cabdff1aSopenharmony_ci .write_trailer = hash_write_trailer, 208cabdff1aSopenharmony_ci .deinit = hash_free, 209cabdff1aSopenharmony_ci .flags = AVFMT_VARIABLE_FPS | AVFMT_TS_NONSTRICT | 210cabdff1aSopenharmony_ci AVFMT_TS_NEGATIVE, 211cabdff1aSopenharmony_ci .priv_class = &md5enc_class, 212cabdff1aSopenharmony_ci}; 213cabdff1aSopenharmony_ci#endif 214cabdff1aSopenharmony_ci 215cabdff1aSopenharmony_ci#if CONFIG_STREAMHASH_MUXER 216cabdff1aSopenharmony_ciconst AVOutputFormat ff_streamhash_muxer = { 217cabdff1aSopenharmony_ci .name = "streamhash", 218cabdff1aSopenharmony_ci .long_name = NULL_IF_CONFIG_SMALL("Per-stream hash testing"), 219cabdff1aSopenharmony_ci .priv_data_size = sizeof(struct HashContext), 220cabdff1aSopenharmony_ci .audio_codec = AV_CODEC_ID_PCM_S16LE, 221cabdff1aSopenharmony_ci .video_codec = AV_CODEC_ID_RAWVIDEO, 222cabdff1aSopenharmony_ci .init = streamhash_init, 223cabdff1aSopenharmony_ci .write_packet = hash_write_packet, 224cabdff1aSopenharmony_ci .write_trailer = hash_write_trailer, 225cabdff1aSopenharmony_ci .deinit = hash_free, 226cabdff1aSopenharmony_ci .flags = AVFMT_VARIABLE_FPS | AVFMT_TS_NONSTRICT | 227cabdff1aSopenharmony_ci AVFMT_TS_NEGATIVE, 228cabdff1aSopenharmony_ci .priv_class = &hash_streamhashenc_class, 229cabdff1aSopenharmony_ci}; 230cabdff1aSopenharmony_ci#endif 231cabdff1aSopenharmony_ci 232cabdff1aSopenharmony_ci#if CONFIG_FRAMEHASH_MUXER || CONFIG_FRAMEMD5_MUXER 233cabdff1aSopenharmony_cistatic void framehash_print_extradata(struct AVFormatContext *s) 234cabdff1aSopenharmony_ci{ 235cabdff1aSopenharmony_ci int i; 236cabdff1aSopenharmony_ci 237cabdff1aSopenharmony_ci for (i = 0; i < s->nb_streams; i++) { 238cabdff1aSopenharmony_ci AVStream *st = s->streams[i]; 239cabdff1aSopenharmony_ci AVCodecParameters *par = st->codecpar; 240cabdff1aSopenharmony_ci if (par->extradata) { 241cabdff1aSopenharmony_ci struct HashContext *c = s->priv_data; 242cabdff1aSopenharmony_ci char buf[AV_HASH_MAX_SIZE*2+1]; 243cabdff1aSopenharmony_ci 244cabdff1aSopenharmony_ci avio_printf(s->pb, "#extradata %d, %31d, ", i, par->extradata_size); 245cabdff1aSopenharmony_ci av_hash_init(c->hashes[0]); 246cabdff1aSopenharmony_ci av_hash_update(c->hashes[0], par->extradata, par->extradata_size); 247cabdff1aSopenharmony_ci av_hash_final_hex(c->hashes[0], buf, sizeof(buf)); 248cabdff1aSopenharmony_ci avio_write(s->pb, buf, strlen(buf)); 249cabdff1aSopenharmony_ci avio_printf(s->pb, "\n"); 250cabdff1aSopenharmony_ci } 251cabdff1aSopenharmony_ci } 252cabdff1aSopenharmony_ci} 253cabdff1aSopenharmony_ci 254cabdff1aSopenharmony_cistatic int framehash_init(struct AVFormatContext *s) 255cabdff1aSopenharmony_ci{ 256cabdff1aSopenharmony_ci int res; 257cabdff1aSopenharmony_ci struct HashContext *c = s->priv_data; 258cabdff1aSopenharmony_ci c->per_stream = 0; 259cabdff1aSopenharmony_ci c->hashes = av_mallocz(sizeof(*c->hashes)); 260cabdff1aSopenharmony_ci if (!c->hashes) 261cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 262cabdff1aSopenharmony_ci res = av_hash_alloc(&c->hashes[0], c->hash_name); 263cabdff1aSopenharmony_ci if (res < 0) 264cabdff1aSopenharmony_ci return res; 265cabdff1aSopenharmony_ci return 0; 266cabdff1aSopenharmony_ci} 267cabdff1aSopenharmony_ci 268cabdff1aSopenharmony_cistatic int framehash_write_header(struct AVFormatContext *s) 269cabdff1aSopenharmony_ci{ 270cabdff1aSopenharmony_ci struct HashContext *c = s->priv_data; 271cabdff1aSopenharmony_ci avio_printf(s->pb, "#format: frame checksums\n"); 272cabdff1aSopenharmony_ci avio_printf(s->pb, "#version: %d\n", c->format_version); 273cabdff1aSopenharmony_ci avio_printf(s->pb, "#hash: %s\n", av_hash_get_name(c->hashes[0])); 274cabdff1aSopenharmony_ci framehash_print_extradata(s); 275cabdff1aSopenharmony_ci ff_framehash_write_header(s); 276cabdff1aSopenharmony_ci avio_printf(s->pb, "#stream#, dts, pts, duration, size, hash\n"); 277cabdff1aSopenharmony_ci return 0; 278cabdff1aSopenharmony_ci} 279cabdff1aSopenharmony_ci 280cabdff1aSopenharmony_cistatic int framehash_write_packet(struct AVFormatContext *s, AVPacket *pkt) 281cabdff1aSopenharmony_ci{ 282cabdff1aSopenharmony_ci struct HashContext *c = s->priv_data; 283cabdff1aSopenharmony_ci char buf[AV_HASH_MAX_SIZE*2+128]; 284cabdff1aSopenharmony_ci int len; 285cabdff1aSopenharmony_ci av_hash_init(c->hashes[0]); 286cabdff1aSopenharmony_ci av_hash_update(c->hashes[0], pkt->data, pkt->size); 287cabdff1aSopenharmony_ci 288cabdff1aSopenharmony_ci snprintf(buf, sizeof(buf) - (AV_HASH_MAX_SIZE * 2 + 1), "%d, %10"PRId64", %10"PRId64", %8"PRId64", %8d, ", 289cabdff1aSopenharmony_ci pkt->stream_index, pkt->dts, pkt->pts, pkt->duration, pkt->size); 290cabdff1aSopenharmony_ci len = strlen(buf); 291cabdff1aSopenharmony_ci av_hash_final_hex(c->hashes[0], buf + len, sizeof(buf) - len); 292cabdff1aSopenharmony_ci avio_write(s->pb, buf, strlen(buf)); 293cabdff1aSopenharmony_ci 294cabdff1aSopenharmony_ci if (c->format_version > 1 && pkt->side_data_elems) { 295cabdff1aSopenharmony_ci int i; 296cabdff1aSopenharmony_ci avio_printf(s->pb, ", S=%d", pkt->side_data_elems); 297cabdff1aSopenharmony_ci for (i = 0; i < pkt->side_data_elems; i++) { 298cabdff1aSopenharmony_ci av_hash_init(c->hashes[0]); 299cabdff1aSopenharmony_ci if (HAVE_BIGENDIAN && pkt->side_data[i].type == AV_PKT_DATA_PALETTE) { 300cabdff1aSopenharmony_ci for (size_t j = 0; j < pkt->side_data[i].size; j += sizeof(uint32_t)) { 301cabdff1aSopenharmony_ci uint32_t data = AV_RL32(pkt->side_data[i].data + j); 302cabdff1aSopenharmony_ci av_hash_update(c->hashes[0], (uint8_t *)&data, sizeof(uint32_t)); 303cabdff1aSopenharmony_ci } 304cabdff1aSopenharmony_ci } else 305cabdff1aSopenharmony_ci av_hash_update(c->hashes[0], pkt->side_data[i].data, pkt->side_data[i].size); 306cabdff1aSopenharmony_ci snprintf(buf, sizeof(buf) - (AV_HASH_MAX_SIZE * 2 + 1), 307cabdff1aSopenharmony_ci ", %8"SIZE_SPECIFIER", ", pkt->side_data[i].size); 308cabdff1aSopenharmony_ci len = strlen(buf); 309cabdff1aSopenharmony_ci av_hash_final_hex(c->hashes[0], buf + len, sizeof(buf) - len); 310cabdff1aSopenharmony_ci avio_write(s->pb, buf, strlen(buf)); 311cabdff1aSopenharmony_ci } 312cabdff1aSopenharmony_ci } 313cabdff1aSopenharmony_ci 314cabdff1aSopenharmony_ci avio_printf(s->pb, "\n"); 315cabdff1aSopenharmony_ci return 0; 316cabdff1aSopenharmony_ci} 317cabdff1aSopenharmony_ci#endif 318cabdff1aSopenharmony_ci 319cabdff1aSopenharmony_ci#if CONFIG_FRAMEHASH_MUXER 320cabdff1aSopenharmony_cistatic const AVClass framehash_class = { 321cabdff1aSopenharmony_ci .class_name = "frame hash muxer", 322cabdff1aSopenharmony_ci .item_name = av_default_item_name, 323cabdff1aSopenharmony_ci .option = framehash_options, 324cabdff1aSopenharmony_ci .version = LIBAVUTIL_VERSION_INT, 325cabdff1aSopenharmony_ci}; 326cabdff1aSopenharmony_ci 327cabdff1aSopenharmony_ciconst AVOutputFormat ff_framehash_muxer = { 328cabdff1aSopenharmony_ci .name = "framehash", 329cabdff1aSopenharmony_ci .long_name = NULL_IF_CONFIG_SMALL("Per-frame hash testing"), 330cabdff1aSopenharmony_ci .priv_data_size = sizeof(struct HashContext), 331cabdff1aSopenharmony_ci .audio_codec = AV_CODEC_ID_PCM_S16LE, 332cabdff1aSopenharmony_ci .video_codec = AV_CODEC_ID_RAWVIDEO, 333cabdff1aSopenharmony_ci .init = framehash_init, 334cabdff1aSopenharmony_ci .write_header = framehash_write_header, 335cabdff1aSopenharmony_ci .write_packet = framehash_write_packet, 336cabdff1aSopenharmony_ci .deinit = hash_free, 337cabdff1aSopenharmony_ci .flags = AVFMT_VARIABLE_FPS | AVFMT_TS_NONSTRICT | 338cabdff1aSopenharmony_ci AVFMT_TS_NEGATIVE, 339cabdff1aSopenharmony_ci .priv_class = &framehash_class, 340cabdff1aSopenharmony_ci}; 341cabdff1aSopenharmony_ci#endif 342cabdff1aSopenharmony_ci 343cabdff1aSopenharmony_ci#if CONFIG_FRAMEMD5_MUXER 344cabdff1aSopenharmony_cistatic const AVClass framemd5_class = { 345cabdff1aSopenharmony_ci .class_name = "frame MD5 muxer", 346cabdff1aSopenharmony_ci .item_name = av_default_item_name, 347cabdff1aSopenharmony_ci .option = framemd5_options, 348cabdff1aSopenharmony_ci .version = LIBAVUTIL_VERSION_INT, 349cabdff1aSopenharmony_ci}; 350cabdff1aSopenharmony_ci 351cabdff1aSopenharmony_ciconst AVOutputFormat ff_framemd5_muxer = { 352cabdff1aSopenharmony_ci .name = "framemd5", 353cabdff1aSopenharmony_ci .long_name = NULL_IF_CONFIG_SMALL("Per-frame MD5 testing"), 354cabdff1aSopenharmony_ci .priv_data_size = sizeof(struct HashContext), 355cabdff1aSopenharmony_ci .audio_codec = AV_CODEC_ID_PCM_S16LE, 356cabdff1aSopenharmony_ci .video_codec = AV_CODEC_ID_RAWVIDEO, 357cabdff1aSopenharmony_ci .init = framehash_init, 358cabdff1aSopenharmony_ci .write_header = framehash_write_header, 359cabdff1aSopenharmony_ci .write_packet = framehash_write_packet, 360cabdff1aSopenharmony_ci .deinit = hash_free, 361cabdff1aSopenharmony_ci .flags = AVFMT_VARIABLE_FPS | AVFMT_TS_NONSTRICT | 362cabdff1aSopenharmony_ci AVFMT_TS_NEGATIVE, 363cabdff1aSopenharmony_ci .priv_class = &framemd5_class, 364cabdff1aSopenharmony_ci}; 365cabdff1aSopenharmony_ci#endif 366