1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * This file is part of FFmpeg. 3cabdff1aSopenharmony_ci * 4cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or 5cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 6cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either 7cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 8cabdff1aSopenharmony_ci * 9cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 10cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 11cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12cabdff1aSopenharmony_ci * Lesser General Public License for more details. 13cabdff1aSopenharmony_ci * 14cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 15cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software 16cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17cabdff1aSopenharmony_ci */ 18cabdff1aSopenharmony_ci 19cabdff1aSopenharmony_ci#include <stdio.h> 20cabdff1aSopenharmony_ci#include <stdint.h> 21cabdff1aSopenharmony_ci#include <stdlib.h> 22cabdff1aSopenharmony_ci 23cabdff1aSopenharmony_ci#include "decode_simple.h" 24cabdff1aSopenharmony_ci 25cabdff1aSopenharmony_ci#include "libavutil/common.h" 26cabdff1aSopenharmony_ci#include "libavutil/pixdesc.h" 27cabdff1aSopenharmony_ci#include "libavutil/error.h" 28cabdff1aSopenharmony_ci#include "libavutil/lfg.h" 29cabdff1aSopenharmony_ci#include "libavutil/random_seed.h" 30cabdff1aSopenharmony_ci#include "libavutil/video_enc_params.h" 31cabdff1aSopenharmony_ci 32cabdff1aSopenharmony_ci#include "libavformat/avformat.h" 33cabdff1aSopenharmony_ci 34cabdff1aSopenharmony_ci#include "libavcodec/avcodec.h" 35cabdff1aSopenharmony_ci 36cabdff1aSopenharmony_ci#include "libswscale/swscale.h" 37cabdff1aSopenharmony_ci 38cabdff1aSopenharmony_citypedef struct PrivData { 39cabdff1aSopenharmony_ci unsigned int random_seed; 40cabdff1aSopenharmony_ci AVLFG lfg; 41cabdff1aSopenharmony_ci 42cabdff1aSopenharmony_ci struct SwsContext *scaler; 43cabdff1aSopenharmony_ci 44cabdff1aSopenharmony_ci int v_shift_dst, h_shift_dst; 45cabdff1aSopenharmony_ci int v_shift_src, h_shift_src; 46cabdff1aSopenharmony_ci 47cabdff1aSopenharmony_ci AVFrame *frame_ref; 48cabdff1aSopenharmony_ci AVFrame *frame_dst; 49cabdff1aSopenharmony_ci} PrivData; 50cabdff1aSopenharmony_ci 51cabdff1aSopenharmony_cistatic int process_frame(DecodeContext *dc, AVFrame *frame) 52cabdff1aSopenharmony_ci{ 53cabdff1aSopenharmony_ci PrivData *pd = dc->opaque; 54cabdff1aSopenharmony_ci int slice_start = 0; 55cabdff1aSopenharmony_ci int ret; 56cabdff1aSopenharmony_ci 57cabdff1aSopenharmony_ci if (!frame) 58cabdff1aSopenharmony_ci return 0; 59cabdff1aSopenharmony_ci 60cabdff1aSopenharmony_ci if (!pd->scaler) { 61cabdff1aSopenharmony_ci pd->scaler = sws_getContext(frame->width, frame->height, frame->format, 62cabdff1aSopenharmony_ci pd->frame_ref->width, pd->frame_ref->height, 63cabdff1aSopenharmony_ci pd->frame_ref->format, 0, NULL, NULL, NULL); 64cabdff1aSopenharmony_ci if (!pd->scaler) 65cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 66cabdff1aSopenharmony_ci 67cabdff1aSopenharmony_ci av_pix_fmt_get_chroma_sub_sample(frame->format, &pd->h_shift_src, &pd->v_shift_src); 68cabdff1aSopenharmony_ci } 69cabdff1aSopenharmony_ci 70cabdff1aSopenharmony_ci /* scale the whole input frame as reference */ 71cabdff1aSopenharmony_ci ret = sws_scale(pd->scaler, (const uint8_t **)frame->data, frame->linesize, 0, frame->height, 72cabdff1aSopenharmony_ci pd->frame_ref->data, pd->frame_ref->linesize); 73cabdff1aSopenharmony_ci if (ret < 0) 74cabdff1aSopenharmony_ci return ret; 75cabdff1aSopenharmony_ci 76cabdff1aSopenharmony_ci /* scale slices with randomly generated heights */ 77cabdff1aSopenharmony_ci while (slice_start < frame->height) { 78cabdff1aSopenharmony_ci int slice_height; 79cabdff1aSopenharmony_ci const uint8_t *src[4]; 80cabdff1aSopenharmony_ci 81cabdff1aSopenharmony_ci slice_height = av_lfg_get(&pd->lfg) % (frame->height - slice_start); 82cabdff1aSopenharmony_ci slice_height = FFALIGN(FFMAX(1, slice_height), 1 << pd->v_shift_src); 83cabdff1aSopenharmony_ci 84cabdff1aSopenharmony_ci for (int j = 0; j < FF_ARRAY_ELEMS(src) && frame->data[j]; j++) { 85cabdff1aSopenharmony_ci int shift = (j == 1 || j == 2) ? pd->v_shift_src : 0; 86cabdff1aSopenharmony_ci src[j] = frame->data[j] + frame->linesize[j] * (slice_start >> shift); 87cabdff1aSopenharmony_ci } 88cabdff1aSopenharmony_ci 89cabdff1aSopenharmony_ci ret = sws_scale(pd->scaler, src, frame->linesize, slice_start, slice_height, 90cabdff1aSopenharmony_ci pd->frame_dst->data, pd->frame_dst->linesize); 91cabdff1aSopenharmony_ci if (ret < 0) 92cabdff1aSopenharmony_ci return ret; 93cabdff1aSopenharmony_ci 94cabdff1aSopenharmony_ci slice_start += slice_height; 95cabdff1aSopenharmony_ci } 96cabdff1aSopenharmony_ci 97cabdff1aSopenharmony_ci /* compare the two results */ 98cabdff1aSopenharmony_ci for (int i = 0; i < 4 && pd->frame_ref->data[i]; i++) { 99cabdff1aSopenharmony_ci int shift = (i == 1 || i == 2) ? pd->v_shift_dst : 0; 100cabdff1aSopenharmony_ci 101cabdff1aSopenharmony_ci if (memcmp(pd->frame_ref->data[i], pd->frame_dst->data[i], 102cabdff1aSopenharmony_ci pd->frame_ref->linesize[i] * (pd->frame_ref->height >> shift))) { 103cabdff1aSopenharmony_ci fprintf(stderr, "mismatch frame %d seed %u\n", 104cabdff1aSopenharmony_ci dc->decoder->frame_number - 1, pd->random_seed); 105cabdff1aSopenharmony_ci return AVERROR(EINVAL); 106cabdff1aSopenharmony_ci } 107cabdff1aSopenharmony_ci } 108cabdff1aSopenharmony_ci 109cabdff1aSopenharmony_ci return 0; 110cabdff1aSopenharmony_ci} 111cabdff1aSopenharmony_ci 112cabdff1aSopenharmony_ciint main(int argc, char **argv) 113cabdff1aSopenharmony_ci{ 114cabdff1aSopenharmony_ci PrivData pd; 115cabdff1aSopenharmony_ci DecodeContext dc; 116cabdff1aSopenharmony_ci 117cabdff1aSopenharmony_ci int width, height; 118cabdff1aSopenharmony_ci enum AVPixelFormat pix_fmt; 119cabdff1aSopenharmony_ci const char *filename; 120cabdff1aSopenharmony_ci int ret = 0; 121cabdff1aSopenharmony_ci 122cabdff1aSopenharmony_ci if (argc <= 4) { 123cabdff1aSopenharmony_ci fprintf(stderr, 124cabdff1aSopenharmony_ci "Usage: %s <input file> <dst width> <dst height> <dst pixfmt> [<random seed>] \n", 125cabdff1aSopenharmony_ci argv[0]); 126cabdff1aSopenharmony_ci return 0; 127cabdff1aSopenharmony_ci } 128cabdff1aSopenharmony_ci 129cabdff1aSopenharmony_ci memset(&pd, 0, sizeof(pd)); 130cabdff1aSopenharmony_ci 131cabdff1aSopenharmony_ci filename = argv[1]; 132cabdff1aSopenharmony_ci width = strtol(argv[2], NULL, 0); 133cabdff1aSopenharmony_ci height = strtol(argv[3], NULL, 0); 134cabdff1aSopenharmony_ci pix_fmt = av_get_pix_fmt(argv[4]); 135cabdff1aSopenharmony_ci 136cabdff1aSopenharmony_ci /* init RNG for generating slice sizes */ 137cabdff1aSopenharmony_ci if (argc >= 6) 138cabdff1aSopenharmony_ci pd.random_seed = strtoul(argv[5], NULL, 0); 139cabdff1aSopenharmony_ci else 140cabdff1aSopenharmony_ci pd.random_seed = av_get_random_seed(); 141cabdff1aSopenharmony_ci 142cabdff1aSopenharmony_ci av_lfg_init(&pd.lfg, pd.random_seed); 143cabdff1aSopenharmony_ci 144cabdff1aSopenharmony_ci av_pix_fmt_get_chroma_sub_sample(pix_fmt, &pd.h_shift_dst, &pd.v_shift_dst); 145cabdff1aSopenharmony_ci 146cabdff1aSopenharmony_ci /* allocate the frames for scaler output */ 147cabdff1aSopenharmony_ci for (int i = 0; i < 2; i++) { 148cabdff1aSopenharmony_ci AVFrame *frame = av_frame_alloc(); 149cabdff1aSopenharmony_ci if (!frame) { 150cabdff1aSopenharmony_ci fprintf(stderr, "Error allocating frames\n"); 151cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 152cabdff1aSopenharmony_ci } 153cabdff1aSopenharmony_ci 154cabdff1aSopenharmony_ci frame->width = width; 155cabdff1aSopenharmony_ci frame->height = height; 156cabdff1aSopenharmony_ci frame->format = pix_fmt; 157cabdff1aSopenharmony_ci 158cabdff1aSopenharmony_ci ret = av_frame_get_buffer(frame, 0); 159cabdff1aSopenharmony_ci if (ret < 0) { 160cabdff1aSopenharmony_ci fprintf(stderr, "Error allocating frame data\n"); 161cabdff1aSopenharmony_ci return ret; 162cabdff1aSopenharmony_ci } 163cabdff1aSopenharmony_ci 164cabdff1aSopenharmony_ci /* make sure the padding is zeroed */ 165cabdff1aSopenharmony_ci for (int j = 0; j < 4 && frame->data[j]; j++) { 166cabdff1aSopenharmony_ci int shift = (j == 1 || j == 2) ? pd.v_shift_dst : 0; 167cabdff1aSopenharmony_ci memset(frame->data[j], 0, 168cabdff1aSopenharmony_ci frame->linesize[j] * (height >> shift)); 169cabdff1aSopenharmony_ci } 170cabdff1aSopenharmony_ci if (i) pd.frame_ref = frame; 171cabdff1aSopenharmony_ci else pd.frame_dst = frame; 172cabdff1aSopenharmony_ci } 173cabdff1aSopenharmony_ci 174cabdff1aSopenharmony_ci ret = ds_open(&dc, filename, 0); 175cabdff1aSopenharmony_ci if (ret < 0) { 176cabdff1aSopenharmony_ci fprintf(stderr, "Error opening the file\n"); 177cabdff1aSopenharmony_ci return ret; 178cabdff1aSopenharmony_ci } 179cabdff1aSopenharmony_ci 180cabdff1aSopenharmony_ci dc.process_frame = process_frame; 181cabdff1aSopenharmony_ci dc.opaque = &pd; 182cabdff1aSopenharmony_ci 183cabdff1aSopenharmony_ci ret = ds_run(&dc); 184cabdff1aSopenharmony_ci 185cabdff1aSopenharmony_ci av_frame_free(&pd.frame_dst); 186cabdff1aSopenharmony_ci av_frame_free(&pd.frame_ref); 187cabdff1aSopenharmony_ci sws_freeContext(pd.scaler); 188cabdff1aSopenharmony_ci ds_free(&dc); 189cabdff1aSopenharmony_ci return ret; 190cabdff1aSopenharmony_ci} 191