2 * Copyright (c) 2001 Fabrice Bellard
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:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
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
37 #include <sys/types.h>
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"
47 static int header
= 0;
49 static int decode(AVCodecContext
*dec_ctx
, AVFrame
*frame
,
52 static uint64_t frame_cnt
= 0;
55 ret
= avcodec_send_packet(dec_ctx
, pkt
);
57 fprintf(stderr
, "Error sending a packet for decoding: %s\n", av_err2str(ret
));
62 const AVPixFmtDescriptor
*desc
;
63 char sum
[AV_HASH_MAX_SIZE
* 2 + 1];
64 struct AVHashContext
*hash
;
66 ret
= avcodec_receive_frame(dec_ctx
, frame
);
67 if (ret
== AVERROR(EAGAIN
) || ret
== AVERROR_EOF
) {
70 fprintf(stderr
, "Error during decoding: %s\n", av_err2str(ret
));
76 "#format: frame checksums\n"
80 "#media_type 0: video\n"
81 "#codec_id 0: rawvideo\n"
82 "#dimensions 0: 352x288\n"
84 "#stream#, dts, pts, duration, size, hash\n");
87 desc
= av_pix_fmt_desc_get(dec_ctx
->pix_fmt
);
88 if ((ret
= av_hash_alloc(&hash
, "md5")) < 0) {
93 for (int i
= 0; i
< frame
->height
; i
++)
94 av_hash_update(hash
, &frame
->data
[0][i
* frame
->linesize
[0]], frame
->width
);
95 for (int i
= 0; i
< frame
->height
>> desc
->log2_chroma_h
; i
++)
96 av_hash_update(hash
, &frame
->data
[1][i
* frame
->linesize
[1]], frame
->width
>> desc
->log2_chroma_w
);
97 for (int i
= 0; i
< frame
->height
>> desc
->log2_chroma_h
; i
++)
98 av_hash_update(hash
, &frame
->data
[2][i
* frame
->linesize
[2]], frame
->width
>> desc
->log2_chroma_w
);
100 av_hash_final_hex(hash
, sum
, av_hash_get_size(hash
) * 2 + 1);
101 printf("0, %10"PRId64
", %10"PRId64
", 1, %8d, %s\n",
102 frame_cnt
, frame_cnt
,
103 (frame
->width
* frame
->height
+ 2 * (frame
->height
>> desc
->log2_chroma_h
) * (frame
->width
>> desc
->log2_chroma_w
)), sum
);
105 av_hash_freep(&hash
);
110 int main(int argc
, char **argv
)
112 const AVCodec
*codec
= NULL
;
113 AVCodecContext
*c
= NULL
;
114 AVFrame
*frame
= NULL
;
115 unsigned int threads
;
119 int nals
= 0, ret
= 0;
123 fprintf(stderr
, "Usage: %s <threads> <input file>\n", argv
[0]);
127 if (!(threads
= strtoul(argv
[1], NULL
, 0)))
129 else if (threads
> MAX_SLICES
)
130 threads
= MAX_SLICES
;
133 setmode(fileno(stdout
), O_BINARY
);
136 if (!(pkt
= av_packet_alloc())) {
140 nal
= av_malloc(MAX_SLICES
* UINT16_MAX
+ AV_INPUT_BUFFER_PADDING_SIZE
);
145 if (!(codec
= avcodec_find_decoder(AV_CODEC_ID_H264
))) {
146 fprintf(stderr
, "Codec not found\n");
151 if (!(c
= avcodec_alloc_context3(codec
))) {
152 fprintf(stderr
, "Could not allocate video codec context\n");
160 c
->flags2
|= AV_CODEC_FLAG2_CHUNKS
;
161 c
->thread_type
= FF_THREAD_SLICE
;
162 c
->thread_count
= threads
;
164 if ((ret
= avcodec_open2(c
, codec
, NULL
)) < 0) {
165 fprintf(stderr
, "Could not open codec\n");
170 if (c
->active_thread_type
!= FF_THREAD_SLICE
) {
171 fprintf(stderr
, "Couldn't activate slice threading: %d\n", c
->active_thread_type
);
176 fprintf(stderr
, "WARN: not using threads, only checking decoding slice NALUs\n");
179 if (!(frame
= av_frame_alloc())) {
180 fprintf(stderr
, "Could not allocate video frame\n");
185 if (!(file
= fopen(argv
[2], "rb"))) {
186 fprintf(stderr
, "Couldn't open NALU file: %s\n", argv
[2]);
193 size_t ret
= fread(&size
, 1, sizeof(uint16_t), file
);
194 if (ret
!= sizeof(uint16_t))
197 size
= av_be2ne16(size
);
198 ret
= fread(p
, 1, size
, file
);
200 perror("Couldn't read data");
205 if (++nals
>= threads
) {
209 if ((decret
= decode(c
, frame
, pkt
)) < 0) {
212 memset(nal
, 0, MAX_SLICES
* UINT16_MAX
+ AV_INPUT_BUFFER_PADDING_SIZE
);
221 if ((ret
= decode(c
, frame
, pkt
)) < 0) {
226 ret
= decode(c
, frame
, NULL
);
233 av_frame_free(&frame
);
234 avcodec_free_context(&c
);
235 av_packet_free(&pkt
);