| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | /* | ||
| 2 | * Copyright (c) 2001 Fabrice Bellard | ||
| 3 | * | ||
| 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| 5 | * of this software and associated documentation files (the "Software"), to deal | ||
| 6 | * in the Software without restriction, including without limitation the rights | ||
| 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
| 8 | * copies of the Software, and to permit persons to whom the Software is | ||
| 9 | * furnished to do so, subject to the following conditions: | ||
| 10 | * | ||
| 11 | * The above copyright notice and this permission notice shall be included in | ||
| 12 | * all copies or substantial portions of the Software. | ||
| 13 | * | ||
| 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
| 20 | * THE SOFTWARE. | ||
| 21 | */ | ||
| 22 | |||
| 23 | #define MAX_SLICES 8 | ||
| 24 | |||
| 25 | #include "config.h" | ||
| 26 | |||
| 27 | #include <stdio.h> | ||
| 28 | #include <stdlib.h> | ||
| 29 | #include <string.h> | ||
| 30 | |||
| 31 | #if HAVE_UNISTD_H | ||
| 32 | #include <unistd.h> | ||
| 33 | #endif | ||
| 34 | #if HAVE_IO_H | ||
| 35 | #include <io.h> | ||
| 36 | #endif | ||
| 37 | #include <sys/types.h> | ||
| 38 | #include <sys/stat.h> | ||
| 39 | #include <fcntl.h> | ||
| 40 | |||
| 41 | #include "libavcodec/avcodec.h" | ||
| 42 | #include "libavutil/mem.h" | ||
| 43 | #include "libavutil/pixdesc.h" | ||
| 44 | #include "libavutil/hash.h" | ||
| 45 | #include "libavutil/bswap.h" | ||
| 46 | |||
| 47 | static int header = 0; | ||
| 48 | |||
| 49 | 757 | static int decode(AVCodecContext *dec_ctx, AVFrame *frame, | |
| 50 | AVPacket *pkt) | ||
| 51 | { | ||
| 52 | static uint64_t frame_cnt = 0; | ||
| 53 | int ret; | ||
| 54 | |||
| 55 | 757 | ret = avcodec_send_packet(dec_ctx, pkt); | |
| 56 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 757 times.
|
757 | if (ret < 0) { |
| 57 | ✗ | fprintf(stderr, "Error sending a packet for decoding: %s\n", av_err2str(ret)); | |
| 58 | ✗ | return ret; | |
| 59 | } | ||
| 60 | |||
| 61 |
1/2✓ Branch 0 taken 1057 times.
✗ Branch 1 not taken.
|
1057 | while (ret >= 0) { |
| 62 | const AVPixFmtDescriptor *desc; | ||
| 63 | char sum[AV_HASH_MAX_SIZE * 2 + 1]; | ||
| 64 | struct AVHashContext *hash; | ||
| 65 | |||
| 66 | 1057 | ret = avcodec_receive_frame(dec_ctx, frame); | |
| 67 |
4/4✓ Branch 0 taken 301 times.
✓ Branch 1 taken 756 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 300 times.
|
1057 | if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { |
| 68 | 757 | return 0; | |
| 69 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 300 times.
|
300 | } else if (ret < 0) { |
| 70 | ✗ | fprintf(stderr, "Error during decoding: %s\n", av_err2str(ret)); | |
| 71 | ✗ | return ret; | |
| 72 | } | ||
| 73 | |||
| 74 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 299 times.
|
300 | if (!header) { |
| 75 | 1 | printf( | |
| 76 | "#format: frame checksums\n" | ||
| 77 | "#version: 2\n" | ||
| 78 | "#hash: MD5\n" | ||
| 79 | "#tb 0: 1/30\n" | ||
| 80 | "#media_type 0: video\n" | ||
| 81 | "#codec_id 0: rawvideo\n" | ||
| 82 | "#dimensions 0: 352x288\n" | ||
| 83 | "#sar 0: 128/117\n" | ||
| 84 | "#stream#, dts, pts, duration, size, hash\n"); | ||
| 85 | 1 | header = 1; | |
| 86 | } | ||
| 87 | 300 | desc = av_pix_fmt_desc_get(dec_ctx->pix_fmt); | |
| 88 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 300 times.
|
300 | if ((ret = av_hash_alloc(&hash, "md5")) < 0) { |
| 89 | ✗ | return ret; | |
| 90 | } | ||
| 91 | 300 | av_hash_init(hash); | |
| 92 | |||
| 93 |
2/2✓ Branch 0 taken 86400 times.
✓ Branch 1 taken 300 times.
|
86700 | for (int i = 0; i < frame->height; i++) |
| 94 | 86400 | av_hash_update(hash, &frame->data[0][i * frame->linesize[0]], frame->width); | |
| 95 |
2/2✓ Branch 0 taken 43200 times.
✓ Branch 1 taken 300 times.
|
43500 | for (int i = 0; i < frame->height >> desc->log2_chroma_h; i++) |
| 96 | 43200 | av_hash_update(hash, &frame->data[1][i * frame->linesize[1]], frame->width >> desc->log2_chroma_w); | |
| 97 |
2/2✓ Branch 0 taken 43200 times.
✓ Branch 1 taken 300 times.
|
43500 | for (int i = 0; i < frame->height >> desc->log2_chroma_h; i++) |
| 98 | 43200 | av_hash_update(hash, &frame->data[2][i * frame->linesize[2]], frame->width >> desc->log2_chroma_w); | |
| 99 | |||
| 100 | 300 | av_hash_final_hex(hash, sum, av_hash_get_size(hash) * 2 + 1); | |
| 101 | 300 | printf("0, %10"PRId64", %10"PRId64", 1, %8d, %s\n", | |
| 102 | frame_cnt, frame_cnt, | ||
| 103 | 300 | (frame->width * frame->height + 2 * (frame->height >> desc->log2_chroma_h) * (frame->width >> desc->log2_chroma_w)), sum); | |
| 104 | 300 | frame_cnt += 1; | |
| 105 | 300 | av_hash_freep(&hash); | |
| 106 | } | ||
| 107 | ✗ | return 0; | |
| 108 | } | ||
| 109 | |||
| 110 | 1 | int main(int argc, char **argv) | |
| 111 | { | ||
| 112 | 1 | const AVCodec *codec = NULL; | |
| 113 | 1 | AVCodecContext *c = NULL; | |
| 114 | 1 | AVFrame *frame = NULL; | |
| 115 | unsigned int threads; | ||
| 116 | AVPacket *pkt; | ||
| 117 | 1 | FILE *file = NULL; | |
| 118 | 1 | char * nal = NULL; | |
| 119 | 1 | int nals = 0, ret = 0; | |
| 120 | char *p; | ||
| 121 | |||
| 122 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (argc < 3) { |
| 123 | ✗ | fprintf(stderr, "Usage: %s <threads> <input file>\n", argv[0]); | |
| 124 | ✗ | return -1; | |
| 125 | } | ||
| 126 | |||
| 127 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
|
1 | if (!(threads = strtoul(argv[1], NULL, 0))) |
| 128 | ✗ | threads = 1; | |
| 129 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | else if (threads > MAX_SLICES) |
| 130 | ✗ | threads = MAX_SLICES; | |
| 131 | |||
| 132 | #ifdef _WIN32 | ||
| 133 | setmode(fileno(stdout), O_BINARY); | ||
| 134 | #endif | ||
| 135 | |||
| 136 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
|
1 | if (!(pkt = av_packet_alloc())) { |
| 137 | ✗ | return -1; | |
| 138 | } | ||
| 139 | |||
| 140 | 1 | nal = av_malloc(MAX_SLICES * UINT16_MAX + AV_INPUT_BUFFER_PADDING_SIZE); | |
| 141 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (!nal) |
| 142 | ✗ | goto err; | |
| 143 | 1 | p = nal; | |
| 144 | |||
| 145 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
|
1 | if (!(codec = avcodec_find_decoder(AV_CODEC_ID_H264))) { |
| 146 | ✗ | fprintf(stderr, "Codec not found\n"); | |
| 147 | ✗ | ret = -1; | |
| 148 | ✗ | goto err; | |
| 149 | } | ||
| 150 | |||
| 151 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
|
1 | if (!(c = avcodec_alloc_context3(codec))) { |
| 152 | ✗ | fprintf(stderr, "Could not allocate video codec context\n"); | |
| 153 | ✗ | ret = -1; | |
| 154 | ✗ | goto err; | |
| 155 | } | ||
| 156 | |||
| 157 | 1 | c->width = 352; | |
| 158 | 1 | c->height = 288; | |
| 159 | |||
| 160 | 1 | c->flags2 |= AV_CODEC_FLAG2_CHUNKS; | |
| 161 | 1 | c->thread_type = FF_THREAD_SLICE; | |
| 162 | 1 | c->thread_count = threads; | |
| 163 | |||
| 164 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
|
1 | if ((ret = avcodec_open2(c, codec, NULL)) < 0) { |
| 165 | ✗ | fprintf(stderr, "Could not open codec\n"); | |
| 166 | ✗ | goto err; | |
| 167 | } | ||
| 168 | |||
| 169 | #if HAVE_THREADS | ||
| 170 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (c->active_thread_type != FF_THREAD_SLICE) { |
| 171 | ✗ | fprintf(stderr, "Couldn't activate slice threading: %d\n", c->active_thread_type); | |
| 172 | ✗ | ret = -1; | |
| 173 | ✗ | goto err; | |
| 174 | } | ||
| 175 | #else | ||
| 176 | fprintf(stderr, "WARN: not using threads, only checking decoding slice NALUs\n"); | ||
| 177 | #endif | ||
| 178 | |||
| 179 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
|
1 | if (!(frame = av_frame_alloc())) { |
| 180 | ✗ | fprintf(stderr, "Could not allocate video frame\n"); | |
| 181 | ✗ | ret = -1; | |
| 182 | ✗ | goto err; | |
| 183 | } | ||
| 184 | |||
| 185 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
|
1 | if (!(file = fopen(argv[2], "rb"))) { |
| 186 | ✗ | fprintf(stderr, "Couldn't open NALU file: %s\n", argv[2]); | |
| 187 | ✗ | ret = -1; | |
| 188 | ✗ | goto err; | |
| 189 | } | ||
| 190 | |||
| 191 | 1511 | while(1) { | |
| 192 | 1512 | uint16_t size = 0; | |
| 193 | 1512 | size_t ret = fread(&size, 1, sizeof(uint16_t), file); | |
| 194 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1511 times.
|
1512 | if (ret != sizeof(uint16_t)) |
| 195 | 1 | break; | |
| 196 | |||
| 197 | 1511 | size = av_be2ne16(size); | |
| 198 | 1511 | ret = fread(p, 1, size, file); | |
| 199 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1511 times.
|
1511 | if (ret != size) { |
| 200 | ✗ | perror("Couldn't read data"); | |
| 201 | ✗ | goto err; | |
| 202 | } | ||
| 203 | 1511 | p += ret; | |
| 204 | |||
| 205 |
2/2✓ Branch 0 taken 755 times.
✓ Branch 1 taken 756 times.
|
1511 | if (++nals >= threads) { |
| 206 | 755 | int decret = 0; | |
| 207 | 755 | pkt->data = nal; | |
| 208 | 755 | pkt->size = p - nal; | |
| 209 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 755 times.
|
755 | if ((decret = decode(c, frame, pkt)) < 0) { |
| 210 | ✗ | goto err; | |
| 211 | } | ||
| 212 | 755 | memset(nal, 0, MAX_SLICES * UINT16_MAX + AV_INPUT_BUFFER_PADDING_SIZE); | |
| 213 | 755 | nals = 0; | |
| 214 | 755 | p = nal; | |
| 215 | } | ||
| 216 | } | ||
| 217 | |||
| 218 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | if (nals) { |
| 219 | 1 | pkt->data = nal; | |
| 220 | 1 | pkt->size = p - nal; | |
| 221 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
|
1 | if ((ret = decode(c, frame, pkt)) < 0) { |
| 222 | ✗ | goto err; | |
| 223 | } | ||
| 224 | } | ||
| 225 | |||
| 226 | 1 | ret = decode(c, frame, NULL); | |
| 227 | |||
| 228 | 1 | err: | |
| 229 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | if (nal) |
| 230 | 1 | av_free(nal); | |
| 231 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | if (file) |
| 232 | 1 | fclose(file); | |
| 233 | 1 | av_frame_free(&frame); | |
| 234 | 1 | avcodec_free_context(&c); | |
| 235 | 1 | av_packet_free(&pkt); | |
| 236 | |||
| 237 | 1 | return ret; | |
| 238 | } | ||
| 239 |