analyzer: show padding

Change-Id: Ia79346bcee77c20def193dc790da665d425539de
diff --git a/examples/analyzer.cc b/examples/analyzer.cc
index 6c2a35f..752f1bd 100644
--- a/examples/analyzer.cc
+++ b/examples/analyzer.cc
@@ -43,6 +43,7 @@
   insp_frame_data frame_data;
 
   aom_codec_ctx_t codec;
+  bool show_padding;
 
  public:
   aom_image_t *image;
@@ -57,6 +58,9 @@
   void close();
   bool step();
 
+  int getWidthPadding() const;
+  int getHeightPadding() const;
+  void togglePadding();
   int getWidth() const;
   int getHeight() const;
 
@@ -67,10 +71,13 @@
 };
 
 AV1Decoder::AV1Decoder()
-    : reader(NULL), info(NULL), decoder(NULL), image(NULL), frame(0) {}
+    : reader(NULL), info(NULL), decoder(NULL), show_padding(false), image(NULL),
+      frame(0) {}
 
 AV1Decoder::~AV1Decoder() {}
 
+void AV1Decoder::togglePadding() { show_padding = !show_padding; }
+
 bool AV1Decoder::open(const wxString &path) {
   reader = aom_video_reader_open(path.mb_str());
   if (!reader) {
@@ -117,9 +124,29 @@
   return false;
 }
 
-int AV1Decoder::getWidth() const { return info->frame_width; }
+int AV1Decoder::getWidth() const {
+  return info->frame_width + 2 * getWidthPadding();
+}
 
-int AV1Decoder::getHeight() const { return info->frame_height; }
+int AV1Decoder::getWidthPadding() const {
+  return show_padding
+             ? AOMMAX(info->frame_width + 16,
+                      ALIGN_POWER_OF_TWO(info->frame_width, 6)) -
+                   info->frame_width
+             : 0;
+}
+
+int AV1Decoder::getHeight() const {
+  return info->frame_height + 2 * getHeightPadding();
+}
+
+int AV1Decoder::getHeightPadding() const {
+  return show_padding
+             ? AOMMAX(info->frame_height + 16,
+                      ALIGN_POWER_OF_TWO(info->frame_height, 6)) -
+                   info->frame_height
+             : 0;
+}
 
 bool AV1Decoder::getAccountingStruct(Accounting **accounting) {
   return aom_codec_control(&codec, AV1_GET_ACCOUNTING, accounting) ==
@@ -173,6 +200,7 @@
   bool open(const wxString &path);
   void close();
   void render();
+  void togglePadding();
   bool nextFrame();
   void refresh();
 
@@ -213,10 +241,16 @@
   unsigned char *cb_row = img->planes[1];
   unsigned char *cr_row = img->planes[2];
   unsigned char *p_row = pixels;
+  int y_width_padding = decoder.getWidthPadding();
+  int cb_width_padding = y_width_padding >> 1;
+  int cr_width_padding = y_width_padding >> 1;
+  int y_height_padding = decoder.getHeightPadding();
+  int cb_height_padding = y_height_padding >> 1;
+  int cr_height_padding = y_height_padding >> 1;
   for (int j = 0; j < decoder.getHeight(); j++) {
-    unsigned char *y = y_row;
-    unsigned char *cb = cb_row;
-    unsigned char *cr = cr_row;
+    unsigned char *y = y_row - y_stride * y_height_padding;
+    unsigned char *cb = cb_row - cb_stride * cb_height_padding;
+    unsigned char *cr = cr_row - cr_stride * cr_height_padding;
     unsigned char *p = p_row;
     for (int i = 0; i < decoder.getWidth(); i++) {
       int64_t yval;
@@ -226,9 +260,9 @@
       unsigned rval;
       unsigned gval;
       unsigned bval;
-      yval = *y;
-      cbval = *cb;
-      crval = *cr;
+      yval = *(y - y_width_padding);
+      cbval = *(cb - cb_width_padding);
+      crval = *(cr - cr_width_padding);
       pmask = plane_mask;
       if (pmask & OD_LUMA_MASK) {
         yval -= 16;
@@ -304,6 +338,11 @@
   printf("\n");
 }
 
+void AnalyzerPanel::togglePadding() {
+  decoder.togglePadding();
+  updateDisplaySize();
+}
+
 bool AnalyzerPanel::nextFrame() {
   if (decoder.step()) {
     refresh();
@@ -407,9 +446,10 @@
   void onClose(wxCommandEvent &event);  // NOLINT
   void onQuit(wxCommandEvent &event);   // NOLINT
 
-  void onZoomIn(wxCommandEvent &event);      // NOLINT
-  void onZoomOut(wxCommandEvent &event);     // NOLINT
-  void onActualSize(wxCommandEvent &event);  // NOLINT
+  void onTogglePadding(wxCommandEvent &event);  // NOLINT
+  void onZoomIn(wxCommandEvent &event);         // NOLINT
+  void onZoomOut(wxCommandEvent &event);        // NOLINT
+  void onActualSize(wxCommandEvent &event);     // NOLINT
 
   void onToggleViewMenuCheckBox(wxCommandEvent &event);          // NOLINT
   void onResetAndToggleViewMenuCheckBox(wxCommandEvent &event);  // NOLINT
@@ -432,13 +472,15 @@
   wxID_SHOW_V,
   wxID_GOTO_FRAME,
   wxID_RESTART,
-  wxID_ACTUAL_SIZE
+  wxID_ACTUAL_SIZE,
+  wxID_PADDING
 };
 
 BEGIN_EVENT_TABLE(AnalyzerFrame, wxFrame)
 EVT_MENU(wxID_OPEN, AnalyzerFrame::onOpen)
 EVT_MENU(wxID_CLOSE, AnalyzerFrame::onClose)
 EVT_MENU(wxID_EXIT, AnalyzerFrame::onQuit)
+EVT_MENU(wxID_PADDING, AnalyzerFrame::onTogglePadding)
 EVT_MENU(wxID_ZOOM_IN, AnalyzerFrame::onZoomIn)
 EVT_MENU(wxID_ZOOM_OUT, AnalyzerFrame::onZoomOut)
 EVT_MENU(wxID_ACTUAL_SIZE, AnalyzerFrame::onActualSize)
@@ -471,6 +513,8 @@
   this->SetAcceleratorTable(accel);
 
   viewMenu = new wxMenu();
+  +viewMenu->Append(wxID_PADDING, _("Toggle padding\tCtrl-p"),
+                    _("Show padding"));
   viewMenu->Append(wxID_ZOOM_IN, _("Zoom-In\tCtrl-+"), _("Double image size"));
   viewMenu->Append(wxID_ZOOM_OUT, _("Zoom-Out\tCtrl--"), _("Half image size"));
   viewMenu->Append(wxID_ACTUAL_SIZE, _("Actual size\tCtrl-0"),
@@ -515,6 +559,13 @@
 
 void AnalyzerFrame::onQuit(wxCommandEvent &WXUNUSED(event)) { Close(true); }
 
+void AnalyzerFrame::onTogglePadding(wxCommandEvent &WXUNUSED(event)) {
+  panel->togglePadding();
+  SetClientSize(panel->GetSize());
+  panel->render();
+  panel->Refresh();
+}
+
 void AnalyzerFrame::onZoomIn(wxCommandEvent &WXUNUSED(event)) {
   setZoom(panel->getZoom() + 1);
 }