aomenc/webmenc: Check for errors.

Test for errors returned by mkvmuxer instead of
taking it on faith that all API calls always work.

Change-Id: Icfa1be7c2f1d37cfb339ecab45ab66625266b109
diff --git a/apps/aomenc.c b/apps/aomenc.c
index 8b5b621..6b2e3e0 100644
--- a/apps/aomenc.c
+++ b/apps/aomenc.c
@@ -1470,9 +1470,11 @@
 #if CONFIG_WEBM_IO
   if (stream->config.write_webm) {
     stream->webm_ctx.stream = stream->file;
-    write_webm_file_header(&stream->webm_ctx, &stream->encoder, cfg,
-                           stream->config.stereo_fmt, global->codec->fourcc,
-                           pixel_aspect_ratio);
+    if (write_webm_file_header(&stream->webm_ctx, &stream->encoder, cfg,
+                               stream->config.stereo_fmt, global->codec->fourcc,
+                               pixel_aspect_ratio) != 0) {
+      fatal("WebM writer initialization failed.");
+    }
   }
 #else
   (void)pixel_aspect_ratio;
@@ -1491,7 +1493,9 @@
 
 #if CONFIG_WEBM_IO
   if (stream->config.write_webm) {
-    write_webm_file_footer(&stream->webm_ctx);
+    if (write_webm_file_footer(&stream->webm_ctx) != 0) {
+      fatal("WebM writer finalization failed.");
+    }
   }
 #endif
 
@@ -1714,7 +1718,9 @@
         update_rate_histogram(stream->rate_hist, cfg, pkt);
 #if CONFIG_WEBM_IO
         if (stream->config.write_webm) {
-          write_webm_block(&stream->webm_ctx, cfg, pkt);
+          if (write_webm_block(&stream->webm_ctx, cfg, pkt) != 0) {
+            fatal("WebM writer failed.");
+          }
         }
 #endif
         if (!stream->config.write_webm) {
diff --git a/common/webmenc.cc b/common/webmenc.cc
index 02f9850..6ae7df6 100644
--- a/common/webmenc.cc
+++ b/common/webmenc.cc
@@ -11,6 +11,8 @@
 
 #include "common/webmenc.h"
 
+#include <stdio.h>
+
 #include <string>
 
 #include "common/av1_config.h"
@@ -23,18 +25,33 @@
 const int kVideoTrackNumber = 1;
 }  // namespace
 
-void write_webm_file_header(struct WebmOutputContext *webm_ctx,
-                            aom_codec_ctx_t *encoder_ctx,
-                            const aom_codec_enc_cfg_t *cfg,
-                            stereo_format_t stereo_fmt, unsigned int fourcc,
-                            const struct AvxRational *par) {
+int write_webm_file_header(struct WebmOutputContext *webm_ctx,
+                           aom_codec_ctx_t *encoder_ctx,
+                           const aom_codec_enc_cfg_t *cfg,
+                           stereo_format_t stereo_fmt, unsigned int fourcc,
+                           const struct AvxRational *par) {
   mkvmuxer::MkvWriter *const writer = new mkvmuxer::MkvWriter(webm_ctx->stream);
   mkvmuxer::Segment *const segment = new mkvmuxer::Segment();
-  segment->Init(writer);
+  if (!writer || !segment) {
+    fprintf(stderr, "webmenc> mkvmuxer objects alloc failed, out of memory?\n");
+    return -1;
+  }
+
+  bool ok = segment->Init(writer);
+  if (!ok) {
+    fprintf(stderr, "webmenc> mkvmuxer Init failed.\n");
+    return -1;
+  }
+
   segment->set_mode(mkvmuxer::Segment::kFile);
   segment->OutputCues(true);
 
   mkvmuxer::SegmentInfo *const info = segment->GetSegmentInfo();
+  if (!info) {
+    fprintf(stderr, "webmenc> Cannot retrieve Segment Info.\n");
+    return -1;
+  }
+
   const uint64_t kTimecodeScale = 1000000;
   info->set_timecode_scale(kTimecodeScale);
   std::string version = "aomenc";
@@ -49,9 +66,15 @@
   mkvmuxer::VideoTrack *const video_track = static_cast<mkvmuxer::VideoTrack *>(
       segment->GetTrackByNumber(video_track_id));
 
+  if (!video_track) {
+    fprintf(stderr, "webmenc> Video track creation failed.\n");
+    return -1;
+  }
+
+  ok = false;
   aom_fixed_buf_t *obu_sequence_header =
       aom_codec_get_global_headers(encoder_ctx);
-  if (obu_sequence_header != NULL) {
+  if (obu_sequence_header) {
     Av1Config av1_config;
     if (get_av1config_from_obu(
             reinterpret_cast<const uint8_t *>(obu_sequence_header->buf),
@@ -60,21 +83,30 @@
       size_t bytes_written = 0;
       if (write_av1config(&av1_config, sizeof(av1_config_buffer),
                           &bytes_written, av1_config_buffer) == 0) {
-        video_track->SetCodecPrivate(av1_config_buffer,
-                                     sizeof(av1_config_buffer));
+        ok = video_track->SetCodecPrivate(av1_config_buffer,
+                                          sizeof(av1_config_buffer));
       }
     }
     free(obu_sequence_header->buf);
     free(obu_sequence_header);
   }
-
-  video_track->SetStereoMode(stereo_fmt);
-  const char *codec_id;
-  switch (fourcc) {
-    case AV1_FOURCC: codec_id = "V_AV1"; break;
-    default: codec_id = "V_AV1"; break;
+  if (!ok) {
+    fprintf(stderr, "webmenc> Unable to set AV1 config.\n");
+    return -1;
   }
-  video_track->set_codec_id(codec_id);
+
+  ok = video_track->SetStereoMode(stereo_fmt);
+  if (!ok) {
+    fprintf(stderr, "webmenc> Unable to set stereo mode.\n");
+    return -1;
+  }
+
+  if (fourcc != AV1_FOURCC) {
+    fprintf(stderr, "webmenc> Unsupported codec (unknown 4 CC).\n");
+    return -1;
+  }
+  video_track->set_codec_id("V_AV1");
+
   if (par->numerator > 1 || par->denominator > 1) {
     // TODO(fgalligan): Add support of DisplayUnit, Display Aspect Ratio type
     // to WebM format.
@@ -83,16 +115,24 @@
     video_track->set_display_width(display_width);
     video_track->set_display_height(cfg->g_h);
   }
+
   if (webm_ctx->debug) {
     video_track->set_uid(kDebugTrackUid);
   }
+
   webm_ctx->writer = writer;
   webm_ctx->segment = segment;
+
+  return 0;
 }
 
-void write_webm_block(struct WebmOutputContext *webm_ctx,
-                      const aom_codec_enc_cfg_t *cfg,
-                      const aom_codec_cx_pkt_t *pkt) {
+int write_webm_block(struct WebmOutputContext *webm_ctx,
+                     const aom_codec_enc_cfg_t *cfg,
+                     const aom_codec_cx_pkt_t *pkt) {
+  if (!webm_ctx->segment) {
+    fprintf(stderr, "webmenc> segment is NULL.\n");
+    return -1;
+  }
   mkvmuxer::Segment *const segment =
       reinterpret_cast<mkvmuxer::Segment *>(webm_ctx->segment);
   int64_t pts_ns = pkt->data.frame.pts * 1000000000ll * cfg->g_timebase.num /
@@ -100,19 +140,34 @@
   if (pts_ns <= webm_ctx->last_pts_ns) pts_ns = webm_ctx->last_pts_ns + 1000000;
   webm_ctx->last_pts_ns = pts_ns;
 
-  segment->AddFrame(static_cast<uint8_t *>(pkt->data.frame.buf),
-                    pkt->data.frame.sz, kVideoTrackNumber, pts_ns,
-                    pkt->data.frame.flags & AOM_FRAME_IS_KEY);
+  if (!segment->AddFrame(static_cast<uint8_t *>(pkt->data.frame.buf),
+                         pkt->data.frame.sz, kVideoTrackNumber, pts_ns,
+                         pkt->data.frame.flags & AOM_FRAME_IS_KEY)) {
+    fprintf(stderr, "webmenc> AddFrame failed.\n");
+    return -1;
+  }
+  return 0;
 }
 
-void write_webm_file_footer(struct WebmOutputContext *webm_ctx) {
+int write_webm_file_footer(struct WebmOutputContext *webm_ctx) {
+  if (!webm_ctx->writer || !webm_ctx->segment) {
+    fprintf(stderr, "webmenc> segment or writer NULL.\n");
+    return -1;
+  }
   mkvmuxer::MkvWriter *const writer =
       reinterpret_cast<mkvmuxer::MkvWriter *>(webm_ctx->writer);
   mkvmuxer::Segment *const segment =
       reinterpret_cast<mkvmuxer::Segment *>(webm_ctx->segment);
-  segment->Finalize();
+  const bool ok = segment->Finalize();
   delete segment;
   delete writer;
   webm_ctx->writer = NULL;
   webm_ctx->segment = NULL;
+
+  if (!ok) {
+    fprintf(stderr, "webmenc> Segment::Finalize failed.\n");
+    return -1;
+  }
+
+  return 0;
 }
diff --git a/common/webmenc.h b/common/webmenc.h
index 9d459a7..4cdfd68 100644
--- a/common/webmenc.h
+++ b/common/webmenc.h
@@ -38,17 +38,20 @@
   STEREO_FORMAT_RIGHT_LEFT = 11
 } stereo_format_t;
 
-void write_webm_file_header(struct WebmOutputContext *webm_ctx,
-                            aom_codec_ctx_t *encoder_ctx,
-                            const aom_codec_enc_cfg_t *cfg,
-                            stereo_format_t stereo_fmt, unsigned int fourcc,
-                            const struct AvxRational *par);
+// The following functions wrap libwebm's mkvmuxer. All functions return 0 upon
+// success, or -1 upon failure.
 
-void write_webm_block(struct WebmOutputContext *webm_ctx,
-                      const aom_codec_enc_cfg_t *cfg,
-                      const aom_codec_cx_pkt_t *pkt);
+int write_webm_file_header(struct WebmOutputContext *webm_ctx,
+                           aom_codec_ctx_t *encoder_ctx,
+                           const aom_codec_enc_cfg_t *cfg,
+                           stereo_format_t stereo_fmt, unsigned int fourcc,
+                           const struct AvxRational *par);
 
-void write_webm_file_footer(struct WebmOutputContext *webm_ctx);
+int write_webm_block(struct WebmOutputContext *webm_ctx,
+                     const aom_codec_enc_cfg_t *cfg,
+                     const aom_codec_cx_pkt_t *pkt);
+
+int write_webm_file_footer(struct WebmOutputContext *webm_ctx);
 
 #ifdef __cplusplus
 }  // extern "C"