2 * This file is part of FFmpeg.
4 * FFmpeg is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * FFmpeg is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with FFmpeg; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 #include "decode_simple.h"
25 #include "libavutil/common.h"
26 #include "libavutil/pixdesc.h"
27 #include "libavutil/error.h"
28 #include "libavutil/lfg.h"
29 #include "libavutil/random_seed.h"
30 #include "libavutil/video_enc_params.h"
32 #include "libavformat/avformat.h"
34 #include "libavcodec/avcodec.h"
36 #include "libswscale/swscale.h"
38 typedef struct PrivData
{
39 unsigned int random_seed
;
42 struct SwsContext
*scaler
;
44 int v_shift_dst
, h_shift_dst
;
45 int v_shift_src
, h_shift_src
;
51 static int process_frame(DecodeContext
*dc
, AVFrame
*frame
)
53 PrivData
*pd
= dc
->opaque
;
61 pd
->scaler
= sws_getContext(frame
->width
, frame
->height
, frame
->format
,
62 pd
->frame_ref
->width
, pd
->frame_ref
->height
,
63 pd
->frame_ref
->format
, 0, NULL
, NULL
, NULL
);
65 return AVERROR(ENOMEM
);
67 av_pix_fmt_get_chroma_sub_sample(frame
->format
, &pd
->h_shift_src
, &pd
->v_shift_src
);
70 /* scale the whole input frame as reference */
71 ret
= sws_scale(pd
->scaler
, (const uint8_t **)frame
->data
, frame
->linesize
, 0, frame
->height
,
72 pd
->frame_ref
->data
, pd
->frame_ref
->linesize
);
76 /* scale slices with randomly generated heights */
77 while (slice_start
< frame
->height
) {
79 const uint8_t *src
[4];
81 slice_height
= av_lfg_get(&pd
->lfg
) % (frame
->height
- slice_start
);
82 slice_height
= FFALIGN(FFMAX(1, slice_height
), 1 << pd
->v_shift_src
);
84 for (int j
= 0; j
< FF_ARRAY_ELEMS(src
) && frame
->data
[j
]; j
++) {
85 int shift
= (j
== 1 || j
== 2) ? pd
->v_shift_src
: 0;
86 src
[j
] = frame
->data
[j
] + frame
->linesize
[j
] * (slice_start
>> shift
);
89 ret
= sws_scale(pd
->scaler
, src
, frame
->linesize
, slice_start
, slice_height
,
90 pd
->frame_dst
->data
, pd
->frame_dst
->linesize
);
94 slice_start
+= slice_height
;
97 /* compare the two results */
98 for (int i
= 0; i
< 4 && pd
->frame_ref
->data
[i
]; i
++) {
99 int shift
= (i
== 1 || i
== 2) ? pd
->v_shift_dst
: 0;
101 if (memcmp(pd
->frame_ref
->data
[i
], pd
->frame_dst
->data
[i
],
102 pd
->frame_ref
->linesize
[i
] * (pd
->frame_ref
->height
>> shift
))) {
103 fprintf(stderr
, "mismatch frame %d seed %u\n",
104 dc
->decoder
->frame_number
- 1, pd
->random_seed
);
105 return AVERROR(EINVAL
);
112 int main(int argc
, char **argv
)
118 enum AVPixelFormat pix_fmt
;
119 const char *filename
;
124 "Usage: %s <input file> <dst width> <dst height> <dst pixfmt> [<random seed>] \n",
129 memset(&pd
, 0, sizeof(pd
));
132 width
= strtol(argv
[2], NULL
, 0);
133 height
= strtol(argv
[3], NULL
, 0);
134 pix_fmt
= av_get_pix_fmt(argv
[4]);
136 /* init RNG for generating slice sizes */
138 pd
.random_seed
= strtoul(argv
[5], NULL
, 0);
140 pd
.random_seed
= av_get_random_seed();
142 av_lfg_init(&pd
.lfg
, pd
.random_seed
);
144 av_pix_fmt_get_chroma_sub_sample(pix_fmt
, &pd
.h_shift_dst
, &pd
.v_shift_dst
);
146 /* allocate the frames for scaler output */
147 for (int i
= 0; i
< 2; i
++) {
148 AVFrame
*frame
= av_frame_alloc();
150 fprintf(stderr
, "Error allocating frames\n");
151 return AVERROR(ENOMEM
);
154 frame
->width
= width
;
155 frame
->height
= height
;
156 frame
->format
= pix_fmt
;
158 ret
= av_frame_get_buffer(frame
, 0);
160 fprintf(stderr
, "Error allocating frame data\n");
164 /* make sure the padding is zeroed */
165 for (int j
= 0; j
< 4 && frame
->data
[j
]; j
++) {
166 int shift
= (j
== 1 || j
== 2) ? pd
.v_shift_dst
: 0;
167 memset(frame
->data
[j
], 0,
168 frame
->linesize
[j
] * (height
>> shift
));
170 if (i
) pd
.frame_ref
= frame
;
171 else pd
.frame_dst
= frame
;
174 ret
= ds_open(&dc
, filename
, 0);
176 fprintf(stderr
, "Error opening the file\n");
180 dc
.process_frame
= process_frame
;
185 av_frame_free(&pd
.frame_dst
);
186 av_frame_free(&pd
.frame_ref
);
187 sws_freeContext(pd
.scaler
);