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