1*77c1e3ccSAndroid Build Coastguard Worker /*
2*77c1e3ccSAndroid Build Coastguard Worker * Copyright (c) 2017, Alliance for Open Media. All rights reserved.
3*77c1e3ccSAndroid Build Coastguard Worker *
4*77c1e3ccSAndroid Build Coastguard Worker * This source code is subject to the terms of the BSD 2 Clause License and
5*77c1e3ccSAndroid Build Coastguard Worker * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
6*77c1e3ccSAndroid Build Coastguard Worker * was not distributed with this source code in the LICENSE file, you can
7*77c1e3ccSAndroid Build Coastguard Worker * obtain it at www.aomedia.org/license/software. If the Alliance for Open
8*77c1e3ccSAndroid Build Coastguard Worker * Media Patent License 1.0 was not distributed with this source code in the
9*77c1e3ccSAndroid Build Coastguard Worker * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
10*77c1e3ccSAndroid Build Coastguard Worker */
11*77c1e3ccSAndroid Build Coastguard Worker #include <wx/wx.h>
12*77c1e3ccSAndroid Build Coastguard Worker #include <wx/aboutdlg.h>
13*77c1e3ccSAndroid Build Coastguard Worker #include <wx/cmdline.h>
14*77c1e3ccSAndroid Build Coastguard Worker #include <wx/dcbuffer.h>
15*77c1e3ccSAndroid Build Coastguard Worker
16*77c1e3ccSAndroid Build Coastguard Worker #include "aom/aom_decoder.h"
17*77c1e3ccSAndroid Build Coastguard Worker #include "aom/aomdx.h"
18*77c1e3ccSAndroid Build Coastguard Worker #include "av1/common/av1_common_int.h"
19*77c1e3ccSAndroid Build Coastguard Worker #include "av1/decoder/accounting.h"
20*77c1e3ccSAndroid Build Coastguard Worker #include "av1/decoder/inspection.h"
21*77c1e3ccSAndroid Build Coastguard Worker #include "common/tools_common.h"
22*77c1e3ccSAndroid Build Coastguard Worker #include "common/video_reader.h"
23*77c1e3ccSAndroid Build Coastguard Worker
24*77c1e3ccSAndroid Build Coastguard Worker #define OD_SIGNMASK(a) (-((a) < 0))
25*77c1e3ccSAndroid Build Coastguard Worker #define OD_FLIPSIGNI(a, b) (((a) + OD_SIGNMASK(b)) ^ OD_SIGNMASK(b))
26*77c1e3ccSAndroid Build Coastguard Worker #define OD_DIV_ROUND(x, y) (((x) + OD_FLIPSIGNI((y) >> 1, x)) / (y))
27*77c1e3ccSAndroid Build Coastguard Worker
28*77c1e3ccSAndroid Build Coastguard Worker enum {
29*77c1e3ccSAndroid Build Coastguard Worker OD_LUMA_MASK = 1 << 0,
30*77c1e3ccSAndroid Build Coastguard Worker OD_CB_MASK = 1 << 1,
31*77c1e3ccSAndroid Build Coastguard Worker OD_CR_MASK = 1 << 2,
32*77c1e3ccSAndroid Build Coastguard Worker OD_ALL_MASK = OD_LUMA_MASK | OD_CB_MASK | OD_CR_MASK
33*77c1e3ccSAndroid Build Coastguard Worker };
34*77c1e3ccSAndroid Build Coastguard Worker
35*77c1e3ccSAndroid Build Coastguard Worker class AV1Decoder {
36*77c1e3ccSAndroid Build Coastguard Worker private:
37*77c1e3ccSAndroid Build Coastguard Worker FILE *input;
38*77c1e3ccSAndroid Build Coastguard Worker wxString path;
39*77c1e3ccSAndroid Build Coastguard Worker
40*77c1e3ccSAndroid Build Coastguard Worker AvxVideoReader *reader;
41*77c1e3ccSAndroid Build Coastguard Worker const AvxVideoInfo *info;
42*77c1e3ccSAndroid Build Coastguard Worker
43*77c1e3ccSAndroid Build Coastguard Worker insp_frame_data frame_data;
44*77c1e3ccSAndroid Build Coastguard Worker
45*77c1e3ccSAndroid Build Coastguard Worker aom_codec_ctx_t codec;
46*77c1e3ccSAndroid Build Coastguard Worker bool show_padding;
47*77c1e3ccSAndroid Build Coastguard Worker
48*77c1e3ccSAndroid Build Coastguard Worker public:
49*77c1e3ccSAndroid Build Coastguard Worker aom_image_t *image;
50*77c1e3ccSAndroid Build Coastguard Worker int frame;
51*77c1e3ccSAndroid Build Coastguard Worker
52*77c1e3ccSAndroid Build Coastguard Worker int plane_mask;
53*77c1e3ccSAndroid Build Coastguard Worker
54*77c1e3ccSAndroid Build Coastguard Worker AV1Decoder();
55*77c1e3ccSAndroid Build Coastguard Worker ~AV1Decoder();
56*77c1e3ccSAndroid Build Coastguard Worker
57*77c1e3ccSAndroid Build Coastguard Worker bool open(const wxString &path);
58*77c1e3ccSAndroid Build Coastguard Worker void close();
59*77c1e3ccSAndroid Build Coastguard Worker bool step();
60*77c1e3ccSAndroid Build Coastguard Worker
61*77c1e3ccSAndroid Build Coastguard Worker int getWidthPadding() const;
62*77c1e3ccSAndroid Build Coastguard Worker int getHeightPadding() const;
63*77c1e3ccSAndroid Build Coastguard Worker void togglePadding();
64*77c1e3ccSAndroid Build Coastguard Worker int getWidth() const;
65*77c1e3ccSAndroid Build Coastguard Worker int getHeight() const;
66*77c1e3ccSAndroid Build Coastguard Worker
67*77c1e3ccSAndroid Build Coastguard Worker bool getAccountingStruct(Accounting **acct);
68*77c1e3ccSAndroid Build Coastguard Worker bool setInspectionCallback();
69*77c1e3ccSAndroid Build Coastguard Worker
70*77c1e3ccSAndroid Build Coastguard Worker static void inspect(void *decoder, void *data);
71*77c1e3ccSAndroid Build Coastguard Worker };
72*77c1e3ccSAndroid Build Coastguard Worker
AV1Decoder()73*77c1e3ccSAndroid Build Coastguard Worker AV1Decoder::AV1Decoder()
74*77c1e3ccSAndroid Build Coastguard Worker : reader(NULL), info(NULL), decoder(NULL), show_padding(false), image(NULL),
75*77c1e3ccSAndroid Build Coastguard Worker frame(0) {}
76*77c1e3ccSAndroid Build Coastguard Worker
~AV1Decoder()77*77c1e3ccSAndroid Build Coastguard Worker AV1Decoder::~AV1Decoder() {}
78*77c1e3ccSAndroid Build Coastguard Worker
togglePadding()79*77c1e3ccSAndroid Build Coastguard Worker void AV1Decoder::togglePadding() { show_padding = !show_padding; }
80*77c1e3ccSAndroid Build Coastguard Worker
open(const wxString & path)81*77c1e3ccSAndroid Build Coastguard Worker bool AV1Decoder::open(const wxString &path) {
82*77c1e3ccSAndroid Build Coastguard Worker reader = aom_video_reader_open(path.mb_str());
83*77c1e3ccSAndroid Build Coastguard Worker if (!reader) {
84*77c1e3ccSAndroid Build Coastguard Worker fprintf(stderr, "Failed to open %s for reading.", path.mb_str().data());
85*77c1e3ccSAndroid Build Coastguard Worker return false;
86*77c1e3ccSAndroid Build Coastguard Worker }
87*77c1e3ccSAndroid Build Coastguard Worker this->path = path;
88*77c1e3ccSAndroid Build Coastguard Worker info = aom_video_reader_get_info(reader);
89*77c1e3ccSAndroid Build Coastguard Worker decoder = get_aom_decoder_by_fourcc(info->codec_fourcc);
90*77c1e3ccSAndroid Build Coastguard Worker if (!decoder) {
91*77c1e3ccSAndroid Build Coastguard Worker fprintf(stderr, "Unknown input codec.");
92*77c1e3ccSAndroid Build Coastguard Worker return false;
93*77c1e3ccSAndroid Build Coastguard Worker }
94*77c1e3ccSAndroid Build Coastguard Worker printf("Using %s\n", aom_codec_iface_name(decoder));
95*77c1e3ccSAndroid Build Coastguard Worker if (aom_codec_dec_init(&codec, decoder, NULL, 0)) {
96*77c1e3ccSAndroid Build Coastguard Worker fprintf(stderr, "Failed to initialize decoder.");
97*77c1e3ccSAndroid Build Coastguard Worker return false;
98*77c1e3ccSAndroid Build Coastguard Worker }
99*77c1e3ccSAndroid Build Coastguard Worker ifd_init(&frame_data, info->frame_width, info->frame_height);
100*77c1e3ccSAndroid Build Coastguard Worker setInspectionCallback();
101*77c1e3ccSAndroid Build Coastguard Worker return true;
102*77c1e3ccSAndroid Build Coastguard Worker }
103*77c1e3ccSAndroid Build Coastguard Worker
close()104*77c1e3ccSAndroid Build Coastguard Worker void AV1Decoder::close() {}
105*77c1e3ccSAndroid Build Coastguard Worker
step()106*77c1e3ccSAndroid Build Coastguard Worker bool AV1Decoder::step() {
107*77c1e3ccSAndroid Build Coastguard Worker if (aom_video_reader_read_frame(reader)) {
108*77c1e3ccSAndroid Build Coastguard Worker size_t frame_size;
109*77c1e3ccSAndroid Build Coastguard Worker const unsigned char *frame_data;
110*77c1e3ccSAndroid Build Coastguard Worker frame_data = aom_video_reader_get_frame(reader, &frame_size);
111*77c1e3ccSAndroid Build Coastguard Worker if (aom_codec_decode(&codec, frame_data, frame_size, NULL)) {
112*77c1e3ccSAndroid Build Coastguard Worker fprintf(stderr, "Failed to decode frame.");
113*77c1e3ccSAndroid Build Coastguard Worker return false;
114*77c1e3ccSAndroid Build Coastguard Worker } else {
115*77c1e3ccSAndroid Build Coastguard Worker aom_codec_iter_t iter = NULL;
116*77c1e3ccSAndroid Build Coastguard Worker image = aom_codec_get_frame(&codec, &iter);
117*77c1e3ccSAndroid Build Coastguard Worker if (image != NULL) {
118*77c1e3ccSAndroid Build Coastguard Worker frame++;
119*77c1e3ccSAndroid Build Coastguard Worker return true;
120*77c1e3ccSAndroid Build Coastguard Worker }
121*77c1e3ccSAndroid Build Coastguard Worker return false;
122*77c1e3ccSAndroid Build Coastguard Worker }
123*77c1e3ccSAndroid Build Coastguard Worker }
124*77c1e3ccSAndroid Build Coastguard Worker return false;
125*77c1e3ccSAndroid Build Coastguard Worker }
126*77c1e3ccSAndroid Build Coastguard Worker
getWidth() const127*77c1e3ccSAndroid Build Coastguard Worker int AV1Decoder::getWidth() const {
128*77c1e3ccSAndroid Build Coastguard Worker return info->frame_width + 2 * getWidthPadding();
129*77c1e3ccSAndroid Build Coastguard Worker }
130*77c1e3ccSAndroid Build Coastguard Worker
getWidthPadding() const131*77c1e3ccSAndroid Build Coastguard Worker int AV1Decoder::getWidthPadding() const {
132*77c1e3ccSAndroid Build Coastguard Worker return show_padding ? AOMMAX(info->frame_width + 16,
133*77c1e3ccSAndroid Build Coastguard Worker ALIGN_POWER_OF_TWO(info->frame_width, 6)) -
134*77c1e3ccSAndroid Build Coastguard Worker info->frame_width
135*77c1e3ccSAndroid Build Coastguard Worker : 0;
136*77c1e3ccSAndroid Build Coastguard Worker }
137*77c1e3ccSAndroid Build Coastguard Worker
getHeight() const138*77c1e3ccSAndroid Build Coastguard Worker int AV1Decoder::getHeight() const {
139*77c1e3ccSAndroid Build Coastguard Worker return info->frame_height + 2 * getHeightPadding();
140*77c1e3ccSAndroid Build Coastguard Worker }
141*77c1e3ccSAndroid Build Coastguard Worker
getHeightPadding() const142*77c1e3ccSAndroid Build Coastguard Worker int AV1Decoder::getHeightPadding() const {
143*77c1e3ccSAndroid Build Coastguard Worker return show_padding ? AOMMAX(info->frame_height + 16,
144*77c1e3ccSAndroid Build Coastguard Worker ALIGN_POWER_OF_TWO(info->frame_height, 6)) -
145*77c1e3ccSAndroid Build Coastguard Worker info->frame_height
146*77c1e3ccSAndroid Build Coastguard Worker : 0;
147*77c1e3ccSAndroid Build Coastguard Worker }
148*77c1e3ccSAndroid Build Coastguard Worker
getAccountingStruct(Accounting ** accounting)149*77c1e3ccSAndroid Build Coastguard Worker bool AV1Decoder::getAccountingStruct(Accounting **accounting) {
150*77c1e3ccSAndroid Build Coastguard Worker return aom_codec_control(&codec, AV1_GET_ACCOUNTING, accounting) ==
151*77c1e3ccSAndroid Build Coastguard Worker AOM_CODEC_OK;
152*77c1e3ccSAndroid Build Coastguard Worker }
153*77c1e3ccSAndroid Build Coastguard Worker
setInspectionCallback()154*77c1e3ccSAndroid Build Coastguard Worker bool AV1Decoder::setInspectionCallback() {
155*77c1e3ccSAndroid Build Coastguard Worker aom_inspect_init ii;
156*77c1e3ccSAndroid Build Coastguard Worker ii.inspect_cb = AV1Decoder::inspect;
157*77c1e3ccSAndroid Build Coastguard Worker ii.inspect_ctx = (void *)this;
158*77c1e3ccSAndroid Build Coastguard Worker return aom_codec_control(&codec, AV1_SET_INSPECTION_CALLBACK, &ii) ==
159*77c1e3ccSAndroid Build Coastguard Worker AOM_CODEC_OK;
160*77c1e3ccSAndroid Build Coastguard Worker }
161*77c1e3ccSAndroid Build Coastguard Worker
inspect(void * pbi,void * data)162*77c1e3ccSAndroid Build Coastguard Worker void AV1Decoder::inspect(void *pbi, void *data) {
163*77c1e3ccSAndroid Build Coastguard Worker AV1Decoder *decoder = (AV1Decoder *)data;
164*77c1e3ccSAndroid Build Coastguard Worker ifd_inspect(&decoder->frame_data, pbi, 0);
165*77c1e3ccSAndroid Build Coastguard Worker }
166*77c1e3ccSAndroid Build Coastguard Worker
167*77c1e3ccSAndroid Build Coastguard Worker #define MIN_ZOOM (1)
168*77c1e3ccSAndroid Build Coastguard Worker #define MAX_ZOOM (4)
169*77c1e3ccSAndroid Build Coastguard Worker
170*77c1e3ccSAndroid Build Coastguard Worker class AnalyzerPanel : public wxPanel {
171*77c1e3ccSAndroid Build Coastguard Worker DECLARE_EVENT_TABLE()
172*77c1e3ccSAndroid Build Coastguard Worker
173*77c1e3ccSAndroid Build Coastguard Worker private:
174*77c1e3ccSAndroid Build Coastguard Worker AV1Decoder decoder;
175*77c1e3ccSAndroid Build Coastguard Worker const wxString path;
176*77c1e3ccSAndroid Build Coastguard Worker
177*77c1e3ccSAndroid Build Coastguard Worker int zoom;
178*77c1e3ccSAndroid Build Coastguard Worker unsigned char *pixels;
179*77c1e3ccSAndroid Build Coastguard Worker
180*77c1e3ccSAndroid Build Coastguard Worker const bool bit_accounting;
181*77c1e3ccSAndroid Build Coastguard Worker double *bpp_q3;
182*77c1e3ccSAndroid Build Coastguard Worker
183*77c1e3ccSAndroid Build Coastguard Worker int plane_mask;
184*77c1e3ccSAndroid Build Coastguard Worker
185*77c1e3ccSAndroid Build Coastguard Worker // The display size is the decode size, scaled by the zoom.
186*77c1e3ccSAndroid Build Coastguard Worker int getDisplayWidth() const;
187*77c1e3ccSAndroid Build Coastguard Worker int getDisplayHeight() const;
188*77c1e3ccSAndroid Build Coastguard Worker
189*77c1e3ccSAndroid Build Coastguard Worker bool updateDisplaySize();
190*77c1e3ccSAndroid Build Coastguard Worker
191*77c1e3ccSAndroid Build Coastguard Worker void computeBitsPerPixel();
192*77c1e3ccSAndroid Build Coastguard Worker
193*77c1e3ccSAndroid Build Coastguard Worker public:
194*77c1e3ccSAndroid Build Coastguard Worker AnalyzerPanel(wxWindow *parent, const wxString &path,
195*77c1e3ccSAndroid Build Coastguard Worker const bool bit_accounting);
196*77c1e3ccSAndroid Build Coastguard Worker ~AnalyzerPanel();
197*77c1e3ccSAndroid Build Coastguard Worker
198*77c1e3ccSAndroid Build Coastguard Worker bool open(const wxString &path);
199*77c1e3ccSAndroid Build Coastguard Worker void close();
200*77c1e3ccSAndroid Build Coastguard Worker void render();
201*77c1e3ccSAndroid Build Coastguard Worker void togglePadding();
202*77c1e3ccSAndroid Build Coastguard Worker bool nextFrame();
203*77c1e3ccSAndroid Build Coastguard Worker void refresh();
204*77c1e3ccSAndroid Build Coastguard Worker
205*77c1e3ccSAndroid Build Coastguard Worker int getZoom() const;
206*77c1e3ccSAndroid Build Coastguard Worker bool setZoom(int zoom);
207*77c1e3ccSAndroid Build Coastguard Worker
208*77c1e3ccSAndroid Build Coastguard Worker void setShowPlane(bool show_plane, int mask);
209*77c1e3ccSAndroid Build Coastguard Worker
210*77c1e3ccSAndroid Build Coastguard Worker void onPaint(wxPaintEvent &event); // NOLINT
211*77c1e3ccSAndroid Build Coastguard Worker };
212*77c1e3ccSAndroid Build Coastguard Worker
BEGIN_EVENT_TABLE(AnalyzerPanel,wxPanel)213*77c1e3ccSAndroid Build Coastguard Worker BEGIN_EVENT_TABLE(AnalyzerPanel, wxPanel)
214*77c1e3ccSAndroid Build Coastguard Worker EVT_PAINT(AnalyzerPanel::onPaint)
215*77c1e3ccSAndroid Build Coastguard Worker END_EVENT_TABLE()
216*77c1e3ccSAndroid Build Coastguard Worker
217*77c1e3ccSAndroid Build Coastguard Worker AnalyzerPanel::AnalyzerPanel(wxWindow *parent, const wxString &path,
218*77c1e3ccSAndroid Build Coastguard Worker const bool bit_accounting)
219*77c1e3ccSAndroid Build Coastguard Worker : wxPanel(parent), path(path), zoom(0), pixels(NULL),
220*77c1e3ccSAndroid Build Coastguard Worker bit_accounting(bit_accounting), bpp_q3(NULL), plane_mask(OD_ALL_MASK) {}
221*77c1e3ccSAndroid Build Coastguard Worker
~AnalyzerPanel()222*77c1e3ccSAndroid Build Coastguard Worker AnalyzerPanel::~AnalyzerPanel() { close(); }
223*77c1e3ccSAndroid Build Coastguard Worker
setShowPlane(bool show_plane,int mask)224*77c1e3ccSAndroid Build Coastguard Worker void AnalyzerPanel::setShowPlane(bool show_plane, int mask) {
225*77c1e3ccSAndroid Build Coastguard Worker if (show_plane) {
226*77c1e3ccSAndroid Build Coastguard Worker plane_mask |= mask;
227*77c1e3ccSAndroid Build Coastguard Worker } else {
228*77c1e3ccSAndroid Build Coastguard Worker plane_mask &= ~mask;
229*77c1e3ccSAndroid Build Coastguard Worker }
230*77c1e3ccSAndroid Build Coastguard Worker }
231*77c1e3ccSAndroid Build Coastguard Worker
render()232*77c1e3ccSAndroid Build Coastguard Worker void AnalyzerPanel::render() {
233*77c1e3ccSAndroid Build Coastguard Worker aom_image_t *img = decoder.image;
234*77c1e3ccSAndroid Build Coastguard Worker const int hbd = !!(img->fmt & AOM_IMG_FMT_HIGHBITDEPTH);
235*77c1e3ccSAndroid Build Coastguard Worker int y_stride = img->stride[0] >> hbd;
236*77c1e3ccSAndroid Build Coastguard Worker int cb_stride = img->stride[1] >> hbd;
237*77c1e3ccSAndroid Build Coastguard Worker int cr_stride = img->stride[2] >> hbd;
238*77c1e3ccSAndroid Build Coastguard Worker int p_stride = 3 * getDisplayWidth();
239*77c1e3ccSAndroid Build Coastguard Worker unsigned char *y_row = img->planes[0];
240*77c1e3ccSAndroid Build Coastguard Worker unsigned char *cb_row = img->planes[1];
241*77c1e3ccSAndroid Build Coastguard Worker unsigned char *cr_row = img->planes[2];
242*77c1e3ccSAndroid Build Coastguard Worker uint16_t *y_row16 = reinterpret_cast<uint16_t *>(y_row);
243*77c1e3ccSAndroid Build Coastguard Worker uint16_t *cb_row16 = reinterpret_cast<uint16_t *>(cb_row);
244*77c1e3ccSAndroid Build Coastguard Worker uint16_t *cr_row16 = reinterpret_cast<uint16_t *>(cr_row);
245*77c1e3ccSAndroid Build Coastguard Worker unsigned char *p_row = pixels;
246*77c1e3ccSAndroid Build Coastguard Worker int y_width_padding = decoder.getWidthPadding();
247*77c1e3ccSAndroid Build Coastguard Worker int cb_width_padding = y_width_padding >> 1;
248*77c1e3ccSAndroid Build Coastguard Worker int cr_width_padding = y_width_padding >> 1;
249*77c1e3ccSAndroid Build Coastguard Worker int y_height_padding = decoder.getHeightPadding();
250*77c1e3ccSAndroid Build Coastguard Worker int cb_height_padding = y_height_padding >> 1;
251*77c1e3ccSAndroid Build Coastguard Worker int cr_height_padding = y_height_padding >> 1;
252*77c1e3ccSAndroid Build Coastguard Worker for (int j = 0; j < decoder.getHeight(); j++) {
253*77c1e3ccSAndroid Build Coastguard Worker unsigned char *y = y_row - y_stride * y_height_padding;
254*77c1e3ccSAndroid Build Coastguard Worker unsigned char *cb = cb_row - cb_stride * cb_height_padding;
255*77c1e3ccSAndroid Build Coastguard Worker unsigned char *cr = cr_row - cr_stride * cr_height_padding;
256*77c1e3ccSAndroid Build Coastguard Worker uint16_t *y16 = y_row16 - y_stride * y_height_padding;
257*77c1e3ccSAndroid Build Coastguard Worker uint16_t *cb16 = cb_row16 - cb_stride * cb_height_padding;
258*77c1e3ccSAndroid Build Coastguard Worker uint16_t *cr16 = cr_row16 - cr_stride * cr_height_padding;
259*77c1e3ccSAndroid Build Coastguard Worker unsigned char *p = p_row;
260*77c1e3ccSAndroid Build Coastguard Worker for (int i = 0; i < decoder.getWidth(); i++) {
261*77c1e3ccSAndroid Build Coastguard Worker int64_t yval;
262*77c1e3ccSAndroid Build Coastguard Worker int64_t cbval;
263*77c1e3ccSAndroid Build Coastguard Worker int64_t crval;
264*77c1e3ccSAndroid Build Coastguard Worker int pmask;
265*77c1e3ccSAndroid Build Coastguard Worker unsigned rval;
266*77c1e3ccSAndroid Build Coastguard Worker unsigned gval;
267*77c1e3ccSAndroid Build Coastguard Worker unsigned bval;
268*77c1e3ccSAndroid Build Coastguard Worker if (hbd) {
269*77c1e3ccSAndroid Build Coastguard Worker yval = *(y16 - y_width_padding);
270*77c1e3ccSAndroid Build Coastguard Worker cbval = *(cb16 - cb_width_padding);
271*77c1e3ccSAndroid Build Coastguard Worker crval = *(cr16 - cr_width_padding);
272*77c1e3ccSAndroid Build Coastguard Worker } else {
273*77c1e3ccSAndroid Build Coastguard Worker yval = *(y - y_width_padding);
274*77c1e3ccSAndroid Build Coastguard Worker cbval = *(cb - cb_width_padding);
275*77c1e3ccSAndroid Build Coastguard Worker crval = *(cr - cr_width_padding);
276*77c1e3ccSAndroid Build Coastguard Worker }
277*77c1e3ccSAndroid Build Coastguard Worker pmask = plane_mask;
278*77c1e3ccSAndroid Build Coastguard Worker if (pmask & OD_LUMA_MASK) {
279*77c1e3ccSAndroid Build Coastguard Worker yval -= 16;
280*77c1e3ccSAndroid Build Coastguard Worker } else {
281*77c1e3ccSAndroid Build Coastguard Worker yval = 128;
282*77c1e3ccSAndroid Build Coastguard Worker }
283*77c1e3ccSAndroid Build Coastguard Worker cbval = ((pmask & OD_CB_MASK) >> 1) * (cbval - 128);
284*77c1e3ccSAndroid Build Coastguard Worker crval = ((pmask & OD_CR_MASK) >> 2) * (crval - 128);
285*77c1e3ccSAndroid Build Coastguard Worker /*This is intentionally slow and very accurate.*/
286*77c1e3ccSAndroid Build Coastguard Worker rval = OD_CLAMPI(
287*77c1e3ccSAndroid Build Coastguard Worker 0,
288*77c1e3ccSAndroid Build Coastguard Worker (int32_t)OD_DIV_ROUND(
289*77c1e3ccSAndroid Build Coastguard Worker 2916394880000LL * yval + 4490222169144LL * crval, 9745792000LL),
290*77c1e3ccSAndroid Build Coastguard Worker 65535);
291*77c1e3ccSAndroid Build Coastguard Worker gval = OD_CLAMPI(0,
292*77c1e3ccSAndroid Build Coastguard Worker (int32_t)OD_DIV_ROUND(2916394880000LL * yval -
293*77c1e3ccSAndroid Build Coastguard Worker 534117096223LL * cbval -
294*77c1e3ccSAndroid Build Coastguard Worker 1334761232047LL * crval,
295*77c1e3ccSAndroid Build Coastguard Worker 9745792000LL),
296*77c1e3ccSAndroid Build Coastguard Worker 65535);
297*77c1e3ccSAndroid Build Coastguard Worker bval = OD_CLAMPI(
298*77c1e3ccSAndroid Build Coastguard Worker 0,
299*77c1e3ccSAndroid Build Coastguard Worker (int32_t)OD_DIV_ROUND(
300*77c1e3ccSAndroid Build Coastguard Worker 2916394880000LL * yval + 5290866304968LL * cbval, 9745792000LL),
301*77c1e3ccSAndroid Build Coastguard Worker 65535);
302*77c1e3ccSAndroid Build Coastguard Worker unsigned char *px_row = p;
303*77c1e3ccSAndroid Build Coastguard Worker for (int v = 0; v < zoom; v++) {
304*77c1e3ccSAndroid Build Coastguard Worker unsigned char *px = px_row;
305*77c1e3ccSAndroid Build Coastguard Worker for (int u = 0; u < zoom; u++) {
306*77c1e3ccSAndroid Build Coastguard Worker *(px + 0) = (unsigned char)(rval >> 8);
307*77c1e3ccSAndroid Build Coastguard Worker *(px + 1) = (unsigned char)(gval >> 8);
308*77c1e3ccSAndroid Build Coastguard Worker *(px + 2) = (unsigned char)(bval >> 8);
309*77c1e3ccSAndroid Build Coastguard Worker px += 3;
310*77c1e3ccSAndroid Build Coastguard Worker }
311*77c1e3ccSAndroid Build Coastguard Worker px_row += p_stride;
312*77c1e3ccSAndroid Build Coastguard Worker }
313*77c1e3ccSAndroid Build Coastguard Worker if (hbd) {
314*77c1e3ccSAndroid Build Coastguard Worker int dc = ((y16 - y_row16) & 1) | (1 - img->x_chroma_shift);
315*77c1e3ccSAndroid Build Coastguard Worker y16++;
316*77c1e3ccSAndroid Build Coastguard Worker cb16 += dc;
317*77c1e3ccSAndroid Build Coastguard Worker cr16 += dc;
318*77c1e3ccSAndroid Build Coastguard Worker } else {
319*77c1e3ccSAndroid Build Coastguard Worker int dc = ((y - y_row) & 1) | (1 - img->x_chroma_shift);
320*77c1e3ccSAndroid Build Coastguard Worker y++;
321*77c1e3ccSAndroid Build Coastguard Worker cb += dc;
322*77c1e3ccSAndroid Build Coastguard Worker cr += dc;
323*77c1e3ccSAndroid Build Coastguard Worker }
324*77c1e3ccSAndroid Build Coastguard Worker p += zoom * 3;
325*77c1e3ccSAndroid Build Coastguard Worker }
326*77c1e3ccSAndroid Build Coastguard Worker int dc = -((j & 1) | (1 - img->y_chroma_shift));
327*77c1e3ccSAndroid Build Coastguard Worker if (hbd) {
328*77c1e3ccSAndroid Build Coastguard Worker y_row16 += y_stride;
329*77c1e3ccSAndroid Build Coastguard Worker cb_row16 += dc & cb_stride;
330*77c1e3ccSAndroid Build Coastguard Worker cr_row16 += dc & cr_stride;
331*77c1e3ccSAndroid Build Coastguard Worker } else {
332*77c1e3ccSAndroid Build Coastguard Worker y_row += y_stride;
333*77c1e3ccSAndroid Build Coastguard Worker cb_row += dc & cb_stride;
334*77c1e3ccSAndroid Build Coastguard Worker cr_row += dc & cr_stride;
335*77c1e3ccSAndroid Build Coastguard Worker }
336*77c1e3ccSAndroid Build Coastguard Worker p_row += zoom * p_stride;
337*77c1e3ccSAndroid Build Coastguard Worker }
338*77c1e3ccSAndroid Build Coastguard Worker }
339*77c1e3ccSAndroid Build Coastguard Worker
computeBitsPerPixel()340*77c1e3ccSAndroid Build Coastguard Worker void AnalyzerPanel::computeBitsPerPixel() {
341*77c1e3ccSAndroid Build Coastguard Worker Accounting *acct;
342*77c1e3ccSAndroid Build Coastguard Worker double bpp_total;
343*77c1e3ccSAndroid Build Coastguard Worker int totals_q3[MAX_SYMBOL_TYPES] = { 0 };
344*77c1e3ccSAndroid Build Coastguard Worker int sym_count[MAX_SYMBOL_TYPES] = { 0 };
345*77c1e3ccSAndroid Build Coastguard Worker decoder.getAccountingStruct(&acct);
346*77c1e3ccSAndroid Build Coastguard Worker for (int j = 0; j < decoder.getHeight(); j++) {
347*77c1e3ccSAndroid Build Coastguard Worker for (int i = 0; i < decoder.getWidth(); i++) {
348*77c1e3ccSAndroid Build Coastguard Worker bpp_q3[j * decoder.getWidth() + i] = 0.0;
349*77c1e3ccSAndroid Build Coastguard Worker }
350*77c1e3ccSAndroid Build Coastguard Worker }
351*77c1e3ccSAndroid Build Coastguard Worker bpp_total = 0;
352*77c1e3ccSAndroid Build Coastguard Worker for (int i = 0; i < acct->syms.num_syms; i++) {
353*77c1e3ccSAndroid Build Coastguard Worker AccountingSymbol *s;
354*77c1e3ccSAndroid Build Coastguard Worker s = &acct->syms.syms[i];
355*77c1e3ccSAndroid Build Coastguard Worker totals_q3[s->id] += s->bits;
356*77c1e3ccSAndroid Build Coastguard Worker sym_count[s->id] += s->samples;
357*77c1e3ccSAndroid Build Coastguard Worker }
358*77c1e3ccSAndroid Build Coastguard Worker printf("=== Frame: %-3i ===\n", decoder.frame - 1);
359*77c1e3ccSAndroid Build Coastguard Worker for (int i = 0; i < acct->syms.dictionary.num_strs; i++) {
360*77c1e3ccSAndroid Build Coastguard Worker if (totals_q3[i]) {
361*77c1e3ccSAndroid Build Coastguard Worker printf("%30s = %10.3f (%f bit/symbol)\n", acct->syms.dictionary.strs[i],
362*77c1e3ccSAndroid Build Coastguard Worker (float)totals_q3[i] / 8, (float)totals_q3[i] / 8 / sym_count[i]);
363*77c1e3ccSAndroid Build Coastguard Worker }
364*77c1e3ccSAndroid Build Coastguard Worker }
365*77c1e3ccSAndroid Build Coastguard Worker printf("\n");
366*77c1e3ccSAndroid Build Coastguard Worker }
367*77c1e3ccSAndroid Build Coastguard Worker
togglePadding()368*77c1e3ccSAndroid Build Coastguard Worker void AnalyzerPanel::togglePadding() {
369*77c1e3ccSAndroid Build Coastguard Worker decoder.togglePadding();
370*77c1e3ccSAndroid Build Coastguard Worker updateDisplaySize();
371*77c1e3ccSAndroid Build Coastguard Worker }
372*77c1e3ccSAndroid Build Coastguard Worker
nextFrame()373*77c1e3ccSAndroid Build Coastguard Worker bool AnalyzerPanel::nextFrame() {
374*77c1e3ccSAndroid Build Coastguard Worker if (decoder.step()) {
375*77c1e3ccSAndroid Build Coastguard Worker refresh();
376*77c1e3ccSAndroid Build Coastguard Worker return true;
377*77c1e3ccSAndroid Build Coastguard Worker }
378*77c1e3ccSAndroid Build Coastguard Worker return false;
379*77c1e3ccSAndroid Build Coastguard Worker }
380*77c1e3ccSAndroid Build Coastguard Worker
refresh()381*77c1e3ccSAndroid Build Coastguard Worker void AnalyzerPanel::refresh() {
382*77c1e3ccSAndroid Build Coastguard Worker if (bit_accounting) {
383*77c1e3ccSAndroid Build Coastguard Worker computeBitsPerPixel();
384*77c1e3ccSAndroid Build Coastguard Worker }
385*77c1e3ccSAndroid Build Coastguard Worker render();
386*77c1e3ccSAndroid Build Coastguard Worker }
387*77c1e3ccSAndroid Build Coastguard Worker
getDisplayWidth() const388*77c1e3ccSAndroid Build Coastguard Worker int AnalyzerPanel::getDisplayWidth() const { return zoom * decoder.getWidth(); }
389*77c1e3ccSAndroid Build Coastguard Worker
getDisplayHeight() const390*77c1e3ccSAndroid Build Coastguard Worker int AnalyzerPanel::getDisplayHeight() const {
391*77c1e3ccSAndroid Build Coastguard Worker return zoom * decoder.getHeight();
392*77c1e3ccSAndroid Build Coastguard Worker }
393*77c1e3ccSAndroid Build Coastguard Worker
updateDisplaySize()394*77c1e3ccSAndroid Build Coastguard Worker bool AnalyzerPanel::updateDisplaySize() {
395*77c1e3ccSAndroid Build Coastguard Worker unsigned char *p = (unsigned char *)malloc(
396*77c1e3ccSAndroid Build Coastguard Worker sizeof(*p) * 3 * getDisplayWidth() * getDisplayHeight());
397*77c1e3ccSAndroid Build Coastguard Worker if (p == NULL) {
398*77c1e3ccSAndroid Build Coastguard Worker return false;
399*77c1e3ccSAndroid Build Coastguard Worker }
400*77c1e3ccSAndroid Build Coastguard Worker free(pixels);
401*77c1e3ccSAndroid Build Coastguard Worker pixels = p;
402*77c1e3ccSAndroid Build Coastguard Worker SetSize(getDisplayWidth(), getDisplayHeight());
403*77c1e3ccSAndroid Build Coastguard Worker return true;
404*77c1e3ccSAndroid Build Coastguard Worker }
405*77c1e3ccSAndroid Build Coastguard Worker
open(const wxString & path)406*77c1e3ccSAndroid Build Coastguard Worker bool AnalyzerPanel::open(const wxString &path) {
407*77c1e3ccSAndroid Build Coastguard Worker if (!decoder.open(path)) {
408*77c1e3ccSAndroid Build Coastguard Worker return false;
409*77c1e3ccSAndroid Build Coastguard Worker }
410*77c1e3ccSAndroid Build Coastguard Worker if (!setZoom(MIN_ZOOM)) {
411*77c1e3ccSAndroid Build Coastguard Worker return false;
412*77c1e3ccSAndroid Build Coastguard Worker }
413*77c1e3ccSAndroid Build Coastguard Worker if (bit_accounting) {
414*77c1e3ccSAndroid Build Coastguard Worker bpp_q3 = (double *)malloc(sizeof(*bpp_q3) * decoder.getWidth() *
415*77c1e3ccSAndroid Build Coastguard Worker decoder.getHeight());
416*77c1e3ccSAndroid Build Coastguard Worker if (bpp_q3 == NULL) {
417*77c1e3ccSAndroid Build Coastguard Worker fprintf(stderr, "Could not allocate memory for bit accounting\n");
418*77c1e3ccSAndroid Build Coastguard Worker close();
419*77c1e3ccSAndroid Build Coastguard Worker return false;
420*77c1e3ccSAndroid Build Coastguard Worker }
421*77c1e3ccSAndroid Build Coastguard Worker }
422*77c1e3ccSAndroid Build Coastguard Worker if (!nextFrame()) {
423*77c1e3ccSAndroid Build Coastguard Worker close();
424*77c1e3ccSAndroid Build Coastguard Worker return false;
425*77c1e3ccSAndroid Build Coastguard Worker }
426*77c1e3ccSAndroid Build Coastguard Worker SetFocus();
427*77c1e3ccSAndroid Build Coastguard Worker return true;
428*77c1e3ccSAndroid Build Coastguard Worker }
429*77c1e3ccSAndroid Build Coastguard Worker
close()430*77c1e3ccSAndroid Build Coastguard Worker void AnalyzerPanel::close() {
431*77c1e3ccSAndroid Build Coastguard Worker decoder.close();
432*77c1e3ccSAndroid Build Coastguard Worker free(pixels);
433*77c1e3ccSAndroid Build Coastguard Worker pixels = NULL;
434*77c1e3ccSAndroid Build Coastguard Worker free(bpp_q3);
435*77c1e3ccSAndroid Build Coastguard Worker bpp_q3 = NULL;
436*77c1e3ccSAndroid Build Coastguard Worker }
437*77c1e3ccSAndroid Build Coastguard Worker
getZoom() const438*77c1e3ccSAndroid Build Coastguard Worker int AnalyzerPanel::getZoom() const { return zoom; }
439*77c1e3ccSAndroid Build Coastguard Worker
setZoom(int z)440*77c1e3ccSAndroid Build Coastguard Worker bool AnalyzerPanel::setZoom(int z) {
441*77c1e3ccSAndroid Build Coastguard Worker if (z <= MAX_ZOOM && z >= MIN_ZOOM && zoom != z) {
442*77c1e3ccSAndroid Build Coastguard Worker int old_zoom = zoom;
443*77c1e3ccSAndroid Build Coastguard Worker zoom = z;
444*77c1e3ccSAndroid Build Coastguard Worker if (!updateDisplaySize()) {
445*77c1e3ccSAndroid Build Coastguard Worker zoom = old_zoom;
446*77c1e3ccSAndroid Build Coastguard Worker return false;
447*77c1e3ccSAndroid Build Coastguard Worker }
448*77c1e3ccSAndroid Build Coastguard Worker return true;
449*77c1e3ccSAndroid Build Coastguard Worker }
450*77c1e3ccSAndroid Build Coastguard Worker return false;
451*77c1e3ccSAndroid Build Coastguard Worker }
452*77c1e3ccSAndroid Build Coastguard Worker
onPaint(wxPaintEvent &)453*77c1e3ccSAndroid Build Coastguard Worker void AnalyzerPanel::onPaint(wxPaintEvent &) {
454*77c1e3ccSAndroid Build Coastguard Worker wxBitmap bmp(wxImage(getDisplayWidth(), getDisplayHeight(), pixels, true));
455*77c1e3ccSAndroid Build Coastguard Worker wxBufferedPaintDC dc(this, bmp);
456*77c1e3ccSAndroid Build Coastguard Worker }
457*77c1e3ccSAndroid Build Coastguard Worker
458*77c1e3ccSAndroid Build Coastguard Worker class AnalyzerFrame : public wxFrame {
459*77c1e3ccSAndroid Build Coastguard Worker DECLARE_EVENT_TABLE()
460*77c1e3ccSAndroid Build Coastguard Worker
461*77c1e3ccSAndroid Build Coastguard Worker private:
462*77c1e3ccSAndroid Build Coastguard Worker AnalyzerPanel *panel;
463*77c1e3ccSAndroid Build Coastguard Worker const bool bit_accounting;
464*77c1e3ccSAndroid Build Coastguard Worker
465*77c1e3ccSAndroid Build Coastguard Worker wxMenu *fileMenu;
466*77c1e3ccSAndroid Build Coastguard Worker wxMenu *viewMenu;
467*77c1e3ccSAndroid Build Coastguard Worker wxMenu *playbackMenu;
468*77c1e3ccSAndroid Build Coastguard Worker
469*77c1e3ccSAndroid Build Coastguard Worker public:
470*77c1e3ccSAndroid Build Coastguard Worker AnalyzerFrame(const bool bit_accounting); // NOLINT
471*77c1e3ccSAndroid Build Coastguard Worker
472*77c1e3ccSAndroid Build Coastguard Worker void onOpen(wxCommandEvent &event); // NOLINT
473*77c1e3ccSAndroid Build Coastguard Worker void onClose(wxCommandEvent &event); // NOLINT
474*77c1e3ccSAndroid Build Coastguard Worker void onQuit(wxCommandEvent &event); // NOLINT
475*77c1e3ccSAndroid Build Coastguard Worker
476*77c1e3ccSAndroid Build Coastguard Worker void onTogglePadding(wxCommandEvent &event); // NOLINT
477*77c1e3ccSAndroid Build Coastguard Worker void onZoomIn(wxCommandEvent &event); // NOLINT
478*77c1e3ccSAndroid Build Coastguard Worker void onZoomOut(wxCommandEvent &event); // NOLINT
479*77c1e3ccSAndroid Build Coastguard Worker void onActualSize(wxCommandEvent &event); // NOLINT
480*77c1e3ccSAndroid Build Coastguard Worker
481*77c1e3ccSAndroid Build Coastguard Worker void onToggleViewMenuCheckBox(wxCommandEvent &event); // NOLINT
482*77c1e3ccSAndroid Build Coastguard Worker void onResetAndToggleViewMenuCheckBox(wxCommandEvent &event); // NOLINT
483*77c1e3ccSAndroid Build Coastguard Worker
484*77c1e3ccSAndroid Build Coastguard Worker void onNextFrame(wxCommandEvent &event); // NOLINT
485*77c1e3ccSAndroid Build Coastguard Worker void onGotoFrame(wxCommandEvent &event); // NOLINT
486*77c1e3ccSAndroid Build Coastguard Worker void onRestart(wxCommandEvent &event); // NOLINT
487*77c1e3ccSAndroid Build Coastguard Worker
488*77c1e3ccSAndroid Build Coastguard Worker void onAbout(wxCommandEvent &event); // NOLINT
489*77c1e3ccSAndroid Build Coastguard Worker
490*77c1e3ccSAndroid Build Coastguard Worker bool open(const wxString &path);
491*77c1e3ccSAndroid Build Coastguard Worker bool setZoom(int zoom);
492*77c1e3ccSAndroid Build Coastguard Worker void updateViewMenu();
493*77c1e3ccSAndroid Build Coastguard Worker };
494*77c1e3ccSAndroid Build Coastguard Worker
495*77c1e3ccSAndroid Build Coastguard Worker enum {
496*77c1e3ccSAndroid Build Coastguard Worker wxID_NEXT_FRAME = 6000,
497*77c1e3ccSAndroid Build Coastguard Worker wxID_SHOW_Y,
498*77c1e3ccSAndroid Build Coastguard Worker wxID_SHOW_U,
499*77c1e3ccSAndroid Build Coastguard Worker wxID_SHOW_V,
500*77c1e3ccSAndroid Build Coastguard Worker wxID_GOTO_FRAME,
501*77c1e3ccSAndroid Build Coastguard Worker wxID_RESTART,
502*77c1e3ccSAndroid Build Coastguard Worker wxID_ACTUAL_SIZE,
503*77c1e3ccSAndroid Build Coastguard Worker wxID_PADDING
504*77c1e3ccSAndroid Build Coastguard Worker };
505*77c1e3ccSAndroid Build Coastguard Worker
BEGIN_EVENT_TABLE(AnalyzerFrame,wxFrame)506*77c1e3ccSAndroid Build Coastguard Worker BEGIN_EVENT_TABLE(AnalyzerFrame, wxFrame)
507*77c1e3ccSAndroid Build Coastguard Worker EVT_MENU(wxID_OPEN, AnalyzerFrame::onOpen)
508*77c1e3ccSAndroid Build Coastguard Worker EVT_MENU(wxID_CLOSE, AnalyzerFrame::onClose)
509*77c1e3ccSAndroid Build Coastguard Worker EVT_MENU(wxID_EXIT, AnalyzerFrame::onQuit)
510*77c1e3ccSAndroid Build Coastguard Worker EVT_MENU(wxID_PADDING, AnalyzerFrame::onTogglePadding)
511*77c1e3ccSAndroid Build Coastguard Worker EVT_MENU(wxID_ZOOM_IN, AnalyzerFrame::onZoomIn)
512*77c1e3ccSAndroid Build Coastguard Worker EVT_MENU(wxID_ZOOM_OUT, AnalyzerFrame::onZoomOut)
513*77c1e3ccSAndroid Build Coastguard Worker EVT_MENU(wxID_ACTUAL_SIZE, AnalyzerFrame::onActualSize)
514*77c1e3ccSAndroid Build Coastguard Worker EVT_MENU(wxID_SHOW_Y, AnalyzerFrame::onResetAndToggleViewMenuCheckBox)
515*77c1e3ccSAndroid Build Coastguard Worker EVT_MENU(wxID_SHOW_U, AnalyzerFrame::onResetAndToggleViewMenuCheckBox)
516*77c1e3ccSAndroid Build Coastguard Worker EVT_MENU(wxID_SHOW_V, AnalyzerFrame::onResetAndToggleViewMenuCheckBox)
517*77c1e3ccSAndroid Build Coastguard Worker EVT_MENU(wxID_NEXT_FRAME, AnalyzerFrame::onNextFrame)
518*77c1e3ccSAndroid Build Coastguard Worker EVT_MENU(wxID_GOTO_FRAME, AnalyzerFrame::onGotoFrame)
519*77c1e3ccSAndroid Build Coastguard Worker EVT_MENU(wxID_RESTART, AnalyzerFrame::onRestart)
520*77c1e3ccSAndroid Build Coastguard Worker EVT_MENU(wxID_ABOUT, AnalyzerFrame::onAbout)
521*77c1e3ccSAndroid Build Coastguard Worker END_EVENT_TABLE()
522*77c1e3ccSAndroid Build Coastguard Worker
523*77c1e3ccSAndroid Build Coastguard Worker AnalyzerFrame::AnalyzerFrame(const bool bit_accounting)
524*77c1e3ccSAndroid Build Coastguard Worker : wxFrame(NULL, wxID_ANY, _("AV1 Stream Analyzer"), wxDefaultPosition,
525*77c1e3ccSAndroid Build Coastguard Worker wxDefaultSize, wxDEFAULT_FRAME_STYLE),
526*77c1e3ccSAndroid Build Coastguard Worker panel(NULL), bit_accounting(bit_accounting) {
527*77c1e3ccSAndroid Build Coastguard Worker wxMenuBar *mb = new wxMenuBar();
528*77c1e3ccSAndroid Build Coastguard Worker
529*77c1e3ccSAndroid Build Coastguard Worker fileMenu = new wxMenu();
530*77c1e3ccSAndroid Build Coastguard Worker fileMenu->Append(wxID_OPEN, _("&Open...\tCtrl-O"), _("Open AV1 file"));
531*77c1e3ccSAndroid Build Coastguard Worker fileMenu->Append(wxID_CLOSE, _("&Close\tCtrl-W"), _("Close AV1 file"));
532*77c1e3ccSAndroid Build Coastguard Worker fileMenu->Enable(wxID_CLOSE, false);
533*77c1e3ccSAndroid Build Coastguard Worker fileMenu->Append(wxID_EXIT, _("E&xit\tCtrl-Q"), _("Quit this program"));
534*77c1e3ccSAndroid Build Coastguard Worker mb->Append(fileMenu, _("&File"));
535*77c1e3ccSAndroid Build Coastguard Worker
536*77c1e3ccSAndroid Build Coastguard Worker wxAcceleratorEntry entries[2];
537*77c1e3ccSAndroid Build Coastguard Worker entries[0].Set(wxACCEL_CTRL, (int)'=', wxID_ZOOM_IN);
538*77c1e3ccSAndroid Build Coastguard Worker entries[1].Set(wxACCEL_CTRL | wxACCEL_SHIFT, (int)'-', wxID_ZOOM_OUT);
539*77c1e3ccSAndroid Build Coastguard Worker wxAcceleratorTable accel(2, entries);
540*77c1e3ccSAndroid Build Coastguard Worker this->SetAcceleratorTable(accel);
541*77c1e3ccSAndroid Build Coastguard Worker
542*77c1e3ccSAndroid Build Coastguard Worker viewMenu = new wxMenu();
543*77c1e3ccSAndroid Build Coastguard Worker +viewMenu->Append(wxID_PADDING, _("Toggle padding\tCtrl-p"),
544*77c1e3ccSAndroid Build Coastguard Worker _("Show padding"));
545*77c1e3ccSAndroid Build Coastguard Worker viewMenu->Append(wxID_ZOOM_IN, _("Zoom-In\tCtrl-+"), _("Double image size"));
546*77c1e3ccSAndroid Build Coastguard Worker viewMenu->Append(wxID_ZOOM_OUT, _("Zoom-Out\tCtrl--"), _("Half image size"));
547*77c1e3ccSAndroid Build Coastguard Worker viewMenu->Append(wxID_ACTUAL_SIZE, _("Actual size\tCtrl-0"),
548*77c1e3ccSAndroid Build Coastguard Worker _("Actual size of the frame"));
549*77c1e3ccSAndroid Build Coastguard Worker viewMenu->AppendSeparator();
550*77c1e3ccSAndroid Build Coastguard Worker viewMenu->AppendCheckItem(wxID_SHOW_Y, _("&Y plane\tCtrl-Y"),
551*77c1e3ccSAndroid Build Coastguard Worker _("Show Y plane"));
552*77c1e3ccSAndroid Build Coastguard Worker viewMenu->AppendCheckItem(wxID_SHOW_U, _("&U plane\tCtrl-U"),
553*77c1e3ccSAndroid Build Coastguard Worker _("Show U plane"));
554*77c1e3ccSAndroid Build Coastguard Worker viewMenu->AppendCheckItem(wxID_SHOW_V, _("&V plane\tCtrl-V"),
555*77c1e3ccSAndroid Build Coastguard Worker _("Show V plane"));
556*77c1e3ccSAndroid Build Coastguard Worker mb->Append(viewMenu, _("&View"));
557*77c1e3ccSAndroid Build Coastguard Worker
558*77c1e3ccSAndroid Build Coastguard Worker playbackMenu = new wxMenu();
559*77c1e3ccSAndroid Build Coastguard Worker playbackMenu->Append(wxID_NEXT_FRAME, _("Next frame\tCtrl-."),
560*77c1e3ccSAndroid Build Coastguard Worker _("Go to next frame"));
561*77c1e3ccSAndroid Build Coastguard Worker /*playbackMenu->Append(wxID_RESTART, _("&Restart\tCtrl-R"),
562*77c1e3ccSAndroid Build Coastguard Worker _("Set video to frame 0"));
563*77c1e3ccSAndroid Build Coastguard Worker playbackMenu->Append(wxID_GOTO_FRAME, _("Jump to Frame\tCtrl-J"),
564*77c1e3ccSAndroid Build Coastguard Worker _("Go to frame number"));*/
565*77c1e3ccSAndroid Build Coastguard Worker mb->Append(playbackMenu, _("&Playback"));
566*77c1e3ccSAndroid Build Coastguard Worker
567*77c1e3ccSAndroid Build Coastguard Worker wxMenu *helpMenu = new wxMenu();
568*77c1e3ccSAndroid Build Coastguard Worker helpMenu->Append(wxID_ABOUT, _("&About...\tF1"), _("Show about dialog"));
569*77c1e3ccSAndroid Build Coastguard Worker mb->Append(helpMenu, _("&Help"));
570*77c1e3ccSAndroid Build Coastguard Worker
571*77c1e3ccSAndroid Build Coastguard Worker SetMenuBar(mb);
572*77c1e3ccSAndroid Build Coastguard Worker
573*77c1e3ccSAndroid Build Coastguard Worker CreateStatusBar(1);
574*77c1e3ccSAndroid Build Coastguard Worker }
575*77c1e3ccSAndroid Build Coastguard Worker
onOpen(wxCommandEvent & WXUNUSED (event))576*77c1e3ccSAndroid Build Coastguard Worker void AnalyzerFrame::onOpen(wxCommandEvent &WXUNUSED(event)) {
577*77c1e3ccSAndroid Build Coastguard Worker wxFileDialog openFileDialog(this, _("Open file"), wxEmptyString,
578*77c1e3ccSAndroid Build Coastguard Worker wxEmptyString, _("AV1 files (*.ivf)|*.ivf"),
579*77c1e3ccSAndroid Build Coastguard Worker wxFD_OPEN | wxFD_FILE_MUST_EXIST);
580*77c1e3ccSAndroid Build Coastguard Worker if (openFileDialog.ShowModal() != wxID_CANCEL) {
581*77c1e3ccSAndroid Build Coastguard Worker open(openFileDialog.GetPath());
582*77c1e3ccSAndroid Build Coastguard Worker }
583*77c1e3ccSAndroid Build Coastguard Worker }
584*77c1e3ccSAndroid Build Coastguard Worker
onClose(wxCommandEvent & WXUNUSED (event))585*77c1e3ccSAndroid Build Coastguard Worker void AnalyzerFrame::onClose(wxCommandEvent &WXUNUSED(event)) {}
586*77c1e3ccSAndroid Build Coastguard Worker
onQuit(wxCommandEvent & WXUNUSED (event))587*77c1e3ccSAndroid Build Coastguard Worker void AnalyzerFrame::onQuit(wxCommandEvent &WXUNUSED(event)) { Close(true); }
588*77c1e3ccSAndroid Build Coastguard Worker
onTogglePadding(wxCommandEvent & WXUNUSED (event))589*77c1e3ccSAndroid Build Coastguard Worker void AnalyzerFrame::onTogglePadding(wxCommandEvent &WXUNUSED(event)) {
590*77c1e3ccSAndroid Build Coastguard Worker panel->togglePadding();
591*77c1e3ccSAndroid Build Coastguard Worker SetClientSize(panel->GetSize());
592*77c1e3ccSAndroid Build Coastguard Worker panel->render();
593*77c1e3ccSAndroid Build Coastguard Worker panel->Refresh();
594*77c1e3ccSAndroid Build Coastguard Worker }
595*77c1e3ccSAndroid Build Coastguard Worker
onZoomIn(wxCommandEvent & WXUNUSED (event))596*77c1e3ccSAndroid Build Coastguard Worker void AnalyzerFrame::onZoomIn(wxCommandEvent &WXUNUSED(event)) {
597*77c1e3ccSAndroid Build Coastguard Worker setZoom(panel->getZoom() + 1);
598*77c1e3ccSAndroid Build Coastguard Worker }
599*77c1e3ccSAndroid Build Coastguard Worker
onZoomOut(wxCommandEvent & WXUNUSED (event))600*77c1e3ccSAndroid Build Coastguard Worker void AnalyzerFrame::onZoomOut(wxCommandEvent &WXUNUSED(event)) {
601*77c1e3ccSAndroid Build Coastguard Worker setZoom(panel->getZoom() - 1);
602*77c1e3ccSAndroid Build Coastguard Worker }
603*77c1e3ccSAndroid Build Coastguard Worker
onActualSize(wxCommandEvent & WXUNUSED (event))604*77c1e3ccSAndroid Build Coastguard Worker void AnalyzerFrame::onActualSize(wxCommandEvent &WXUNUSED(event)) {
605*77c1e3ccSAndroid Build Coastguard Worker setZoom(MIN_ZOOM);
606*77c1e3ccSAndroid Build Coastguard Worker }
607*77c1e3ccSAndroid Build Coastguard Worker
onToggleViewMenuCheckBox(wxCommandEvent & event)608*77c1e3ccSAndroid Build Coastguard Worker void AnalyzerFrame::onToggleViewMenuCheckBox(wxCommandEvent &event) { // NOLINT
609*77c1e3ccSAndroid Build Coastguard Worker GetMenuBar()->Check(event.GetId(), event.IsChecked());
610*77c1e3ccSAndroid Build Coastguard Worker updateViewMenu();
611*77c1e3ccSAndroid Build Coastguard Worker }
612*77c1e3ccSAndroid Build Coastguard Worker
onResetAndToggleViewMenuCheckBox(wxCommandEvent & event)613*77c1e3ccSAndroid Build Coastguard Worker void AnalyzerFrame::onResetAndToggleViewMenuCheckBox(
614*77c1e3ccSAndroid Build Coastguard Worker wxCommandEvent &event) { // NOLINT
615*77c1e3ccSAndroid Build Coastguard Worker int id = event.GetId();
616*77c1e3ccSAndroid Build Coastguard Worker if (id != wxID_SHOW_Y && id != wxID_SHOW_U && id != wxID_SHOW_V) {
617*77c1e3ccSAndroid Build Coastguard Worker GetMenuBar()->Check(wxID_SHOW_Y, true);
618*77c1e3ccSAndroid Build Coastguard Worker GetMenuBar()->Check(wxID_SHOW_U, true);
619*77c1e3ccSAndroid Build Coastguard Worker GetMenuBar()->Check(wxID_SHOW_V, true);
620*77c1e3ccSAndroid Build Coastguard Worker }
621*77c1e3ccSAndroid Build Coastguard Worker onToggleViewMenuCheckBox(event);
622*77c1e3ccSAndroid Build Coastguard Worker }
623*77c1e3ccSAndroid Build Coastguard Worker
onNextFrame(wxCommandEvent & WXUNUSED (event))624*77c1e3ccSAndroid Build Coastguard Worker void AnalyzerFrame::onNextFrame(wxCommandEvent &WXUNUSED(event)) {
625*77c1e3ccSAndroid Build Coastguard Worker panel->nextFrame();
626*77c1e3ccSAndroid Build Coastguard Worker panel->Refresh(false);
627*77c1e3ccSAndroid Build Coastguard Worker }
628*77c1e3ccSAndroid Build Coastguard Worker
onGotoFrame(wxCommandEvent & WXUNUSED (event))629*77c1e3ccSAndroid Build Coastguard Worker void AnalyzerFrame::onGotoFrame(wxCommandEvent &WXUNUSED(event)) {}
630*77c1e3ccSAndroid Build Coastguard Worker
onRestart(wxCommandEvent & WXUNUSED (event))631*77c1e3ccSAndroid Build Coastguard Worker void AnalyzerFrame::onRestart(wxCommandEvent &WXUNUSED(event)) {}
632*77c1e3ccSAndroid Build Coastguard Worker
onAbout(wxCommandEvent & WXUNUSED (event))633*77c1e3ccSAndroid Build Coastguard Worker void AnalyzerFrame::onAbout(wxCommandEvent &WXUNUSED(event)) {
634*77c1e3ccSAndroid Build Coastguard Worker wxAboutDialogInfo info;
635*77c1e3ccSAndroid Build Coastguard Worker info.SetName(_("AV1 Bitstream Analyzer"));
636*77c1e3ccSAndroid Build Coastguard Worker info.SetVersion(_("0.1-beta"));
637*77c1e3ccSAndroid Build Coastguard Worker info.SetDescription(
638*77c1e3ccSAndroid Build Coastguard Worker _("This program implements a bitstream analyzer for AV1"));
639*77c1e3ccSAndroid Build Coastguard Worker info.SetCopyright(
640*77c1e3ccSAndroid Build Coastguard Worker wxT("(C) 2017 Alliance for Open Media <[email protected]>"));
641*77c1e3ccSAndroid Build Coastguard Worker wxAboutBox(info);
642*77c1e3ccSAndroid Build Coastguard Worker }
643*77c1e3ccSAndroid Build Coastguard Worker
open(const wxString & path)644*77c1e3ccSAndroid Build Coastguard Worker bool AnalyzerFrame::open(const wxString &path) {
645*77c1e3ccSAndroid Build Coastguard Worker panel = new AnalyzerPanel(this, path, bit_accounting);
646*77c1e3ccSAndroid Build Coastguard Worker if (panel->open(path)) {
647*77c1e3ccSAndroid Build Coastguard Worker SetClientSize(panel->GetSize());
648*77c1e3ccSAndroid Build Coastguard Worker return true;
649*77c1e3ccSAndroid Build Coastguard Worker } else {
650*77c1e3ccSAndroid Build Coastguard Worker delete panel;
651*77c1e3ccSAndroid Build Coastguard Worker return false;
652*77c1e3ccSAndroid Build Coastguard Worker }
653*77c1e3ccSAndroid Build Coastguard Worker }
654*77c1e3ccSAndroid Build Coastguard Worker
setZoom(int zoom)655*77c1e3ccSAndroid Build Coastguard Worker bool AnalyzerFrame::setZoom(int zoom) {
656*77c1e3ccSAndroid Build Coastguard Worker if (panel->setZoom(zoom)) {
657*77c1e3ccSAndroid Build Coastguard Worker GetMenuBar()->Enable(wxID_ACTUAL_SIZE, zoom != MIN_ZOOM);
658*77c1e3ccSAndroid Build Coastguard Worker GetMenuBar()->Enable(wxID_ZOOM_IN, zoom != MAX_ZOOM);
659*77c1e3ccSAndroid Build Coastguard Worker GetMenuBar()->Enable(wxID_ZOOM_OUT, zoom != MIN_ZOOM);
660*77c1e3ccSAndroid Build Coastguard Worker SetClientSize(panel->GetSize());
661*77c1e3ccSAndroid Build Coastguard Worker panel->render();
662*77c1e3ccSAndroid Build Coastguard Worker panel->Refresh();
663*77c1e3ccSAndroid Build Coastguard Worker return true;
664*77c1e3ccSAndroid Build Coastguard Worker }
665*77c1e3ccSAndroid Build Coastguard Worker return false;
666*77c1e3ccSAndroid Build Coastguard Worker }
667*77c1e3ccSAndroid Build Coastguard Worker
updateViewMenu()668*77c1e3ccSAndroid Build Coastguard Worker void AnalyzerFrame::updateViewMenu() {
669*77c1e3ccSAndroid Build Coastguard Worker panel->setShowPlane(GetMenuBar()->IsChecked(wxID_SHOW_Y), OD_LUMA_MASK);
670*77c1e3ccSAndroid Build Coastguard Worker panel->setShowPlane(GetMenuBar()->IsChecked(wxID_SHOW_U), OD_CB_MASK);
671*77c1e3ccSAndroid Build Coastguard Worker panel->setShowPlane(GetMenuBar()->IsChecked(wxID_SHOW_V), OD_CR_MASK);
672*77c1e3ccSAndroid Build Coastguard Worker SetClientSize(panel->GetSize());
673*77c1e3ccSAndroid Build Coastguard Worker panel->render();
674*77c1e3ccSAndroid Build Coastguard Worker panel->Refresh(false);
675*77c1e3ccSAndroid Build Coastguard Worker }
676*77c1e3ccSAndroid Build Coastguard Worker
677*77c1e3ccSAndroid Build Coastguard Worker class Analyzer : public wxApp {
678*77c1e3ccSAndroid Build Coastguard Worker private:
679*77c1e3ccSAndroid Build Coastguard Worker AnalyzerFrame *frame;
680*77c1e3ccSAndroid Build Coastguard Worker
681*77c1e3ccSAndroid Build Coastguard Worker public:
682*77c1e3ccSAndroid Build Coastguard Worker void OnInitCmdLine(wxCmdLineParser &parser); // NOLINT
683*77c1e3ccSAndroid Build Coastguard Worker bool OnCmdLineParsed(wxCmdLineParser &parser); // NOLINT
684*77c1e3ccSAndroid Build Coastguard Worker };
685*77c1e3ccSAndroid Build Coastguard Worker
686*77c1e3ccSAndroid Build Coastguard Worker static const wxCmdLineEntryDesc CMD_LINE_DESC[] = {
687*77c1e3ccSAndroid Build Coastguard Worker { wxCMD_LINE_SWITCH, _("h"), _("help"), _("Display this help and exit."),
688*77c1e3ccSAndroid Build Coastguard Worker wxCMD_LINE_VAL_NONE, wxCMD_LINE_OPTION_HELP },
689*77c1e3ccSAndroid Build Coastguard Worker { wxCMD_LINE_SWITCH, _("a"), _("bit-accounting"), _("Enable bit accounting"),
690*77c1e3ccSAndroid Build Coastguard Worker wxCMD_LINE_VAL_NONE, wxCMD_LINE_PARAM_OPTIONAL },
691*77c1e3ccSAndroid Build Coastguard Worker { wxCMD_LINE_PARAM, NULL, NULL, _("input.ivf"), wxCMD_LINE_VAL_STRING,
692*77c1e3ccSAndroid Build Coastguard Worker wxCMD_LINE_PARAM_OPTIONAL },
693*77c1e3ccSAndroid Build Coastguard Worker { wxCMD_LINE_NONE }
694*77c1e3ccSAndroid Build Coastguard Worker };
695*77c1e3ccSAndroid Build Coastguard Worker
OnInitCmdLine(wxCmdLineParser & parser)696*77c1e3ccSAndroid Build Coastguard Worker void Analyzer::OnInitCmdLine(wxCmdLineParser &parser) { // NOLINT
697*77c1e3ccSAndroid Build Coastguard Worker parser.SetDesc(CMD_LINE_DESC);
698*77c1e3ccSAndroid Build Coastguard Worker parser.SetSwitchChars(_("-"));
699*77c1e3ccSAndroid Build Coastguard Worker }
700*77c1e3ccSAndroid Build Coastguard Worker
OnCmdLineParsed(wxCmdLineParser & parser)701*77c1e3ccSAndroid Build Coastguard Worker bool Analyzer::OnCmdLineParsed(wxCmdLineParser &parser) { // NOLINT
702*77c1e3ccSAndroid Build Coastguard Worker bool bit_accounting = parser.Found(_("a"));
703*77c1e3ccSAndroid Build Coastguard Worker if (bit_accounting && !CONFIG_ACCOUNTING) {
704*77c1e3ccSAndroid Build Coastguard Worker fprintf(stderr,
705*77c1e3ccSAndroid Build Coastguard Worker "Bit accounting support not found. "
706*77c1e3ccSAndroid Build Coastguard Worker "Recompile with:\n./cmake -DCONFIG_ACCOUNTING=1\n");
707*77c1e3ccSAndroid Build Coastguard Worker return false;
708*77c1e3ccSAndroid Build Coastguard Worker }
709*77c1e3ccSAndroid Build Coastguard Worker frame = new AnalyzerFrame(parser.Found(_("a")));
710*77c1e3ccSAndroid Build Coastguard Worker frame->Show();
711*77c1e3ccSAndroid Build Coastguard Worker if (parser.GetParamCount() > 0) {
712*77c1e3ccSAndroid Build Coastguard Worker return frame->open(parser.GetParam(0));
713*77c1e3ccSAndroid Build Coastguard Worker }
714*77c1e3ccSAndroid Build Coastguard Worker return true;
715*77c1e3ccSAndroid Build Coastguard Worker }
716*77c1e3ccSAndroid Build Coastguard Worker
usage_exit(void)717*77c1e3ccSAndroid Build Coastguard Worker void usage_exit(void) {
718*77c1e3ccSAndroid Build Coastguard Worker fprintf(stderr, "uhh\n");
719*77c1e3ccSAndroid Build Coastguard Worker exit(EXIT_FAILURE);
720*77c1e3ccSAndroid Build Coastguard Worker }
721*77c1e3ccSAndroid Build Coastguard Worker
722*77c1e3ccSAndroid Build Coastguard Worker IMPLEMENT_APP(Analyzer)
723