LCOV - code coverage report
Current view: top level - libavformat - hashenc.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 40 69 58.0 %
Date: 2017-12-18 06:23:41 Functions: 4 7 57.1 %

          Line data    Source code
       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;
      32             :     struct AVHashContext *hash;
      33             :     char *hash_name;
      34             :     int format_version;
      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           0 : static int hash_write_header(struct AVFormatContext *s)
      57             : {
      58           0 :     struct HashContext *c = s->priv_data;
      59           0 :     int res = av_hash_alloc(&c->hash, c->hash_name);
      60           0 :     if (res < 0)
      61           0 :         return res;
      62           0 :     av_hash_init(c->hash);
      63           0 :     return 0;
      64             : }
      65             : 
      66           0 : static int hash_write_packet(struct AVFormatContext *s, AVPacket *pkt)
      67             : {
      68           0 :     struct HashContext *c = s->priv_data;
      69           0 :     av_hash_update(c->hash, pkt->data, pkt->size);
      70           0 :     return 0;
      71             : }
      72             : 
      73           0 : static int hash_write_trailer(struct AVFormatContext *s)
      74             : {
      75           0 :     struct HashContext *c = s->priv_data;
      76             :     char buf[AV_HASH_MAX_SIZE*2+128];
      77           0 :     snprintf(buf, sizeof(buf) - 200, "%s=", av_hash_get_name(c->hash));
      78             : 
      79           0 :     av_hash_final_hex(c->hash, buf + strlen(buf), sizeof(buf) - strlen(buf));
      80           0 :     av_strlcatf(buf, sizeof(buf), "\n");
      81           0 :     avio_write(s->pb, buf, strlen(buf));
      82           0 :     avio_flush(s->pb);
      83             : 
      84           0 :     av_hash_freep(&c->hash);
      85           0 :     return 0;
      86             : }
      87             : #endif
      88             : 
      89             : #if CONFIG_HASH_MUXER
      90             : static const AVClass hashenc_class = {
      91             :     .class_name = "hash encoder class",
      92             :     .item_name  = av_default_item_name,
      93             :     .option     = hash_options,
      94             :     .version    = LIBAVUTIL_VERSION_INT,
      95             : };
      96             : 
      97             : AVOutputFormat ff_hash_muxer = {
      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,
     106             :     .flags             = AVFMT_VARIABLE_FPS | AVFMT_TS_NONSTRICT |
     107             :                          AVFMT_TS_NEGATIVE,
     108             :     .priv_class        = &hashenc_class,
     109             : };
     110             : #endif
     111             : 
     112             : #if CONFIG_MD5_MUXER
     113             : static const AVClass md5enc_class = {
     114             :     .class_name = "MD5 encoder class",
     115             :     .item_name  = av_default_item_name,
     116             :     .option     = md5_options,
     117             :     .version    = LIBAVUTIL_VERSION_INT,
     118             : };
     119             : 
     120             : AVOutputFormat ff_md5_muxer = {
     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,
     129             :     .flags             = AVFMT_VARIABLE_FPS | AVFMT_TS_NONSTRICT |
     130             :                          AVFMT_TS_NEGATIVE,
     131             :     .priv_class        = &md5enc_class,
     132             : };
     133             : #endif
     134             : 
     135             : #if CONFIG_FRAMEHASH_MUXER || CONFIG_FRAMEMD5_MUXER
     136         318 : static void framehash_print_extradata(struct AVFormatContext *s)
     137             : {
     138             :     int i;
     139             : 
     140         637 :     for (i = 0; i < s->nb_streams; i++) {
     141         319 :         AVStream *st = s->streams[i];
     142         319 :         AVCodecParameters *par = st->codecpar;
     143         319 :         if (par->extradata) {
     144          15 :             struct HashContext *c = s->priv_data;
     145             :             char buf[AV_HASH_MAX_SIZE*2+1];
     146             : 
     147          15 :             avio_printf(s->pb, "#extradata %d, %31d, ", i, par->extradata_size);
     148          15 :             av_hash_init(c->hash);
     149          15 :             av_hash_update(c->hash, par->extradata, par->extradata_size);
     150          15 :             av_hash_final_hex(c->hash, buf, sizeof(buf));
     151          15 :             avio_write(s->pb, buf, strlen(buf));
     152          15 :             avio_printf(s->pb, "\n");
     153             :         }
     154             :     }
     155         318 : }
     156             : 
     157         318 : static int framehash_write_header(struct AVFormatContext *s)
     158             : {
     159         318 :     struct HashContext *c = s->priv_data;
     160         318 :     int res = av_hash_alloc(&c->hash, c->hash_name);
     161         318 :     if (res < 0)
     162           0 :         return res;
     163         318 :     avio_printf(s->pb, "#format: frame checksums\n");
     164         318 :     avio_printf(s->pb, "#version: %d\n", c->format_version);
     165         318 :     avio_printf(s->pb, "#hash: %s\n", av_hash_get_name(c->hash));
     166         318 :     framehash_print_extradata(s);
     167         318 :     ff_framehash_write_header(s);
     168         318 :     avio_printf(s->pb, "#stream#, dts,        pts, duration,     size, hash\n");
     169         318 :     return 0;
     170             : }
     171             : 
     172        5532 : static int framehash_write_packet(struct AVFormatContext *s, AVPacket *pkt)
     173             : {
     174        5532 :     struct HashContext *c = s->priv_data;
     175             :     char buf[AV_HASH_MAX_SIZE*2+128];
     176             :     int len;
     177        5532 :     av_hash_init(c->hash);
     178        5532 :     av_hash_update(c->hash, pkt->data, pkt->size);
     179             : 
     180        5532 :     snprintf(buf, sizeof(buf) - (AV_HASH_MAX_SIZE * 2 + 1), "%d, %10"PRId64", %10"PRId64", %8"PRId64", %8d, ",
     181             :              pkt->stream_index, pkt->dts, pkt->pts, pkt->duration, pkt->size);
     182        5532 :     len = strlen(buf);
     183        5532 :     av_hash_final_hex(c->hash, buf + len, sizeof(buf) - len);
     184        5532 :     avio_write(s->pb, buf, strlen(buf));
     185             : 
     186        5532 :     if (c->format_version > 1 && pkt->side_data_elems) {
     187             :         int i, j;
     188           0 :         avio_printf(s->pb, ", S=%d", pkt->side_data_elems);
     189           0 :         for (i = 0; i < pkt->side_data_elems; i++) {
     190           0 :             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
     197           0 :                 av_hash_update(c->hash, pkt->side_data[i].data, pkt->side_data[i].size);
     198           0 :             snprintf(buf, sizeof(buf) - (AV_HASH_MAX_SIZE * 2 + 1), ", %8d, ", pkt->side_data[i].size);
     199           0 :             len = strlen(buf);
     200           0 :             av_hash_final_hex(c->hash, buf + len, sizeof(buf) - len);
     201           0 :             avio_write(s->pb, buf, strlen(buf));
     202             :         }
     203             :     }
     204             : 
     205        5532 :     avio_printf(s->pb, "\n");
     206        5532 :     avio_flush(s->pb);
     207        5532 :     return 0;
     208             : }
     209             : 
     210         318 : static int framehash_write_trailer(struct AVFormatContext *s)
     211             : {
     212         318 :     struct HashContext *c = s->priv_data;
     213         318 :     av_hash_freep(&c->hash);
     214         318 :     return 0;
     215             : }
     216             : #endif
     217             : 
     218             : #if CONFIG_FRAMEHASH_MUXER
     219             : static const AVClass framehash_class = {
     220             :     .class_name = "frame hash encoder class",
     221             :     .item_name  = av_default_item_name,
     222             :     .option     = hash_options,
     223             :     .version    = LIBAVUTIL_VERSION_INT,
     224             : };
     225             : 
     226             : AVOutputFormat ff_framehash_muxer = {
     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,
     235             :     .flags             = AVFMT_VARIABLE_FPS | AVFMT_TS_NONSTRICT |
     236             :                          AVFMT_TS_NEGATIVE,
     237             :     .priv_class        = &framehash_class,
     238             : };
     239             : #endif
     240             : 
     241             : #if CONFIG_FRAMEMD5_MUXER
     242             : static const AVClass framemd5_class = {
     243             :     .class_name = "frame hash encoder class",
     244             :     .item_name  = av_default_item_name,
     245             :     .option     = md5_options,
     246             :     .version    = LIBAVUTIL_VERSION_INT,
     247             : };
     248             : 
     249             : AVOutputFormat ff_framemd5_muxer = {
     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,
     258             :     .flags             = AVFMT_VARIABLE_FPS | AVFMT_TS_NONSTRICT |
     259             :                          AVFMT_TS_NEGATIVE,
     260             :     .priv_class        = &framemd5_class,
     261             : };
     262             : #endif

Generated by: LCOV version 1.13