Change who allocated the MediaPipe's shared buffer.

Have the MediaPipe's implementor receive a client allocated shared buffer
instead of having the client fetch a shared buffer from the implementor.

BUG=
R=dalesat@chromium.org

Review URL: https://codereview.chromium.org/1694963002 .
diff --git a/examples/audio_play_test/play_tone.cc b/examples/audio_play_test/play_tone.cc
index fdc18f2..321261b 100644
--- a/examples/audio_play_test/play_tone.cc
+++ b/examples/audio_play_test/play_tone.cc
@@ -121,7 +121,6 @@
 
   // Configure our sink for 16-bit 48KHz mono.
   AudioTrackConfigurationPtr cfg = AudioTrackConfiguration::New();
-  cfg->max_frames = USecToBytes(BUF_DEPTH_USEC) / FRAME_BYTES;
 
   LpcmMediaTypeDetailsPtr pcm_cfg = LpcmMediaTypeDetails::New();
   pcm_cfg->sample_format     = LpcmSampleFormat::SIGNED_16;
@@ -140,6 +139,7 @@
   // proxy, pass its interface to our circular buffer helper, set up our
   // high/low water marks, register our callback, and start to buffer our audio.
   audio_pipe_.reset(new CircularBufferMediaPipeAdapter(pipe.Pass()));
+  audio_pipe_->Init(USecToBytes(BUF_DEPTH_USEC));
   audio_pipe_->SetSignalCallback(
   [this](MediaResult res) -> void {
     GenerateToneCbk(res);
diff --git a/examples/audio_play_test/play_wav.cc b/examples/audio_play_test/play_wav.cc
index 03cb392..6b89231 100644
--- a/examples/audio_play_test/play_wav.cc
+++ b/examples/audio_play_test/play_wav.cc
@@ -267,7 +267,6 @@
 
   AudioTrackConfigurationPtr cfg;
   cfg = AudioTrackConfiguration::New();
-  cfg->max_frames = USecToFrames(BUF_DEPTH_USEC);
   cfg->audio_frame_ratio = tmp.numerator;
   cfg->media_time_ratio  = tmp.denominator;
 
@@ -296,6 +295,7 @@
   // Set up our media pipe helper, configure its callback and water marks to
   // kick off the playback process.
   audio_pipe_.reset(new CircularBufferMediaPipeAdapter(media_pipe.Pass()));
+  audio_pipe_->Init(USecToBytes(BUF_DEPTH_USEC));
   audio_pipe_->SetWatermarks(USecToBytes(BUF_HI_WATER_USEC),
                              USecToBytes(BUF_LO_WATER_USEC));
   audio_pipe_->SetSignalCallback(
diff --git a/mojo/dart/packages/mojo_services/lib/mojo/media/audio_track.mojom.dart b/mojo/dart/packages/mojo_services/lib/mojo/media/audio_track.mojom.dart
index 127421d..4121604 100644
--- a/mojo/dart/packages/mojo_services/lib/mojo/media/audio_track.mojom.dart
+++ b/mojo/dart/packages/mojo_services/lib/mojo/media/audio_track.mojom.dart
@@ -109,10 +109,9 @@
 
 class AudioTrackConfiguration extends bindings.Struct {
   static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(32, 0)
+    const bindings.StructDataHeader(24, 0)
   ];
   media_types_mojom.MediaType mediaType = null;
-  int maxFrames = 0;
   int audioFrameRatio = 1;
   int mediaTimeRatio = 1;
 
@@ -158,15 +157,11 @@
     }
     if (mainDataHeader.version >= 0) {
       
-      result.maxFrames = decoder0.decodeUint64(16);
+      result.audioFrameRatio = decoder0.decodeUint32(16);
     }
     if (mainDataHeader.version >= 0) {
       
-      result.audioFrameRatio = decoder0.decodeUint32(24);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.mediaTimeRatio = decoder0.decodeUint32(28);
+      result.mediaTimeRatio = decoder0.decodeUint32(20);
     }
     return result;
   }
@@ -181,21 +176,14 @@
       rethrow;
     }
     try {
-      encoder0.encodeUint64(maxFrames, 16);
-    } on bindings.MojoCodecError catch(e) {
-      e.message = "Error encountered while encoding field "
-          "maxFrames of struct AudioTrackConfiguration: $e";
-      rethrow;
-    }
-    try {
-      encoder0.encodeUint32(audioFrameRatio, 24);
+      encoder0.encodeUint32(audioFrameRatio, 16);
     } on bindings.MojoCodecError catch(e) {
       e.message = "Error encountered while encoding field "
           "audioFrameRatio of struct AudioTrackConfiguration: $e";
       rethrow;
     }
     try {
-      encoder0.encodeUint32(mediaTimeRatio, 28);
+      encoder0.encodeUint32(mediaTimeRatio, 20);
     } on bindings.MojoCodecError catch(e) {
       e.message = "Error encountered while encoding field "
           "mediaTimeRatio of struct AudioTrackConfiguration: $e";
@@ -206,7 +194,6 @@
   String toString() {
     return "AudioTrackConfiguration("
            "mediaType: $mediaType" ", "
-           "maxFrames: $maxFrames" ", "
            "audioFrameRatio: $audioFrameRatio" ", "
            "mediaTimeRatio: $mediaTimeRatio" ")";
   }
@@ -214,7 +201,6 @@
   Map toJson() {
     Map map = new Map();
     map["mediaType"] = mediaType;
-    map["maxFrames"] = maxFrames;
     map["audioFrameRatio"] = audioFrameRatio;
     map["mediaTimeRatio"] = mediaTimeRatio;
     return map;
diff --git a/mojo/dart/packages/mojo_services/lib/mojo/media/media_pipe.mojom.dart b/mojo/dart/packages/mojo_services/lib/mojo/media/media_pipe.mojom.dart
index a367aa6..ecf7139 100644
--- a/mojo/dart/packages/mojo_services/lib/mojo/media/media_pipe.mojom.dart
+++ b/mojo/dart/packages/mojo_services/lib/mojo/media/media_pipe.mojom.dart
@@ -252,17 +252,16 @@
 
 
 
-class MediaPipeState extends bindings.Struct {
+class _MediaPipeSetBufferParams extends bindings.Struct {
   static const List<bindings.StructDataHeader> kVersions = const [
     const bindings.StructDataHeader(24, 0)
   ];
-  static const int kMaxPayloadLen = 4611686018427387903;
-  core.MojoSharedBuffer payloadBuffer = null;
-  int payloadBufferLen = 0;
+  core.MojoSharedBuffer buffer = null;
+  int size = 0;
 
-  MediaPipeState() : super(kVersions.last.size);
+  _MediaPipeSetBufferParams() : super(kVersions.last.size);
 
-  static MediaPipeState deserialize(bindings.Message message) {
+  static _MediaPipeSetBufferParams deserialize(bindings.Message message) {
     var decoder = new bindings.Decoder(message);
     var result = decode(decoder);
     if (decoder.excessHandles != null) {
@@ -271,11 +270,11 @@
     return result;
   }
 
-  static MediaPipeState decode(bindings.Decoder decoder0) {
+  static _MediaPipeSetBufferParams decode(bindings.Decoder decoder0) {
     if (decoder0 == null) {
       return null;
     }
-    MediaPipeState result = new MediaPipeState();
+    _MediaPipeSetBufferParams result = new _MediaPipeSetBufferParams();
 
     var mainDataHeader = decoder0.decodeStructDataHeader();
     if (mainDataHeader.version <= kVersions.last.version) {
@@ -297,11 +296,11 @@
     }
     if (mainDataHeader.version >= 0) {
       
-      result.payloadBuffer = decoder0.decodeSharedBufferHandle(8, false);
+      result.buffer = decoder0.decodeSharedBufferHandle(8, false);
     }
     if (mainDataHeader.version >= 0) {
       
-      result.payloadBufferLen = decoder0.decodeUint64(16);
+      result.size = decoder0.decodeUint64(16);
     }
     return result;
   }
@@ -309,159 +308,25 @@
   void encode(bindings.Encoder encoder) {
     var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
     try {
-      encoder0.encodeSharedBufferHandle(payloadBuffer, 8, false);
+      encoder0.encodeSharedBufferHandle(buffer, 8, false);
     } on bindings.MojoCodecError catch(e) {
       e.message = "Error encountered while encoding field "
-          "payloadBuffer of struct MediaPipeState: $e";
+          "buffer of struct _MediaPipeSetBufferParams: $e";
       rethrow;
     }
     try {
-      encoder0.encodeUint64(payloadBufferLen, 16);
+      encoder0.encodeUint64(size, 16);
     } on bindings.MojoCodecError catch(e) {
       e.message = "Error encountered while encoding field "
-          "payloadBufferLen of struct MediaPipeState: $e";
+          "size of struct _MediaPipeSetBufferParams: $e";
       rethrow;
     }
   }
 
   String toString() {
-    return "MediaPipeState("
-           "payloadBuffer: $payloadBuffer" ", "
-           "payloadBufferLen: $payloadBufferLen" ")";
-  }
-
-  Map toJson() {
-    throw new bindings.MojoCodecError(
-        'Object containing handles cannot be encoded to JSON.');
-  }
-}
-
-
-
-
-class _MediaPipeGetStateParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(8, 0)
-  ];
-
-  _MediaPipeGetStateParams() : super(kVersions.last.size);
-
-  static _MediaPipeGetStateParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    if (decoder.excessHandles != null) {
-      decoder.excessHandles.forEach((h) => h.close());
-    }
-    return result;
-  }
-
-  static _MediaPipeGetStateParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    _MediaPipeGetStateParams result = new _MediaPipeGetStateParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    encoder.getStructEncoderAtOffset(kVersions.last);
-  }
-
-  String toString() {
-    return "_MediaPipeGetStateParams("")";
-  }
-
-  Map toJson() {
-    Map map = new Map();
-    return map;
-  }
-}
-
-
-
-
-class MediaPipeGetStateResponseParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(16, 0)
-  ];
-  MediaPipeState state = null;
-
-  MediaPipeGetStateResponseParams() : super(kVersions.last.size);
-
-  static MediaPipeGetStateResponseParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    if (decoder.excessHandles != null) {
-      decoder.excessHandles.forEach((h) => h.close());
-    }
-    return result;
-  }
-
-  static MediaPipeGetStateResponseParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    MediaPipeGetStateResponseParams result = new MediaPipeGetStateResponseParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(8, false);
-      result.state = MediaPipeState.decode(decoder1);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    try {
-      encoder0.encodeStruct(state, 8, false);
-    } on bindings.MojoCodecError catch(e) {
-      e.message = "Error encountered while encoding field "
-          "state of struct MediaPipeGetStateResponseParams: $e";
-      rethrow;
-    }
-  }
-
-  String toString() {
-    return "MediaPipeGetStateResponseParams("
-           "state: $state" ")";
+    return "_MediaPipeSetBufferParams("
+           "buffer: $buffer" ", "
+           "size: $size" ")";
   }
 
   Map toJson() {
@@ -746,7 +611,7 @@
 
 
 
-const int _MediaPipe_getStateName = 0;
+const int _MediaPipe_setBufferName = 0;
 const int _MediaPipe_sendPacketName = 1;
 const int _MediaPipe_flushName = 2;
   
@@ -819,9 +684,10 @@
 
 abstract class MediaPipe {
   static const String serviceName = null;
-  dynamic getState([Function responseFactory = null]);
+  void setBuffer(core.MojoSharedBuffer buffer, int size);
   dynamic sendPacket(MediaPacket packet,[Function responseFactory = null]);
   dynamic flush([Function responseFactory = null]);
+  static const int kMaxBufferLen = 4611686018427387903;
 }
 
 
@@ -845,26 +711,6 @@
 
   void handleResponse(bindings.ServiceMessage message) {
     switch (message.header.type) {
-      case _MediaPipe_getStateName:
-        var r = MediaPipeGetStateResponseParams.deserialize(
-            message.payload);
-        if (!message.header.hasRequestId) {
-          proxyError("Expected a message with a valid request Id.");
-          return;
-        }
-        Completer c = completerMap[message.header.requestId];
-        if (c == null) {
-          proxyError(
-              "Message had unknown request Id: ${message.header.requestId}");
-          return;
-        }
-        completerMap.remove(message.header.requestId);
-        if (c.isCompleted) {
-          proxyError("Response completer already completed");
-          return;
-        }
-        c.complete(r);
-        break;
       case _MediaPipe_sendPacketName:
         var r = MediaPipeSendPacketResponseParams.deserialize(
             message.payload);
@@ -923,13 +769,15 @@
   _MediaPipeProxyImpl _proxyImpl;
 
   _MediaPipeProxyCalls(this._proxyImpl);
-    dynamic getState([Function responseFactory = null]) {
-      var params = new _MediaPipeGetStateParams();
-      return _proxyImpl.sendMessageWithRequestId(
-          params,
-          _MediaPipe_getStateName,
-          -1,
-          bindings.MessageHeader.kMessageExpectsResponse);
+    void setBuffer(core.MojoSharedBuffer buffer, int size) {
+      if (!_proxyImpl.isBound) {
+        _proxyImpl.proxyError("The Proxy is closed.");
+        return;
+      }
+      var params = new _MediaPipeSetBufferParams();
+      params.buffer = buffer;
+      params.size = size;
+      _proxyImpl.sendMessage(params, _MediaPipe_setBufferName);
     }
     dynamic sendPacket(MediaPacket packet,[Function responseFactory = null]) {
       var params = new _MediaPipeSendPacketParams();
@@ -1029,11 +877,6 @@
   }
 
 
-  MediaPipeGetStateResponseParams _MediaPipeGetStateResponseParamsFactory(MediaPipeState state) {
-    var mojo_factory_result = new MediaPipeGetStateResponseParams();
-    mojo_factory_result.state = state;
-    return mojo_factory_result;
-  }
   MediaPipeSendPacketResponseParams _MediaPipeSendPacketResponseParamsFactory(MediaPipeSendResult result) {
     var mojo_factory_result = new MediaPipeSendPacketResponseParams();
     mojo_factory_result.result = result;
@@ -1052,27 +895,10 @@
     }
     assert(_impl != null);
     switch (message.header.type) {
-      case _MediaPipe_getStateName:
-        var params = _MediaPipeGetStateParams.deserialize(
+      case _MediaPipe_setBufferName:
+        var params = _MediaPipeSetBufferParams.deserialize(
             message.payload);
-        var response = _impl.getState(_MediaPipeGetStateResponseParamsFactory);
-        if (response is Future) {
-          return response.then((response) {
-            if (response != null) {
-              return buildResponseWithId(
-                  response,
-                  _MediaPipe_getStateName,
-                  message.header.requestId,
-                  bindings.MessageHeader.kMessageIsResponse);
-            }
-          });
-        } else if (response != null) {
-          return buildResponseWithId(
-              response,
-              _MediaPipe_getStateName,
-              message.header.requestId,
-              bindings.MessageHeader.kMessageIsResponse);
-        }
+        _impl.setBuffer(params.buffer, params.size);
         break;
       case _MediaPipe_sendPacketName:
         var params = _MediaPipeSendPacketParams.deserialize(
diff --git a/mojo/services/media/audio/interfaces/audio_track.mojom b/mojo/services/media/audio/interfaces/audio_track.mojom
index 3456485..a8b8e07 100644
--- a/mojo/services/media/audio/interfaces/audio_track.mojom
+++ b/mojo/services/media/audio/interfaces/audio_track.mojom
@@ -19,9 +19,6 @@
   // The media type to use.
   MediaType media_type;
 
-  // Desired maximum buffer size, in frames of audio.
-  uint64 max_frames;
-
   // Ratio of audio frames to media time ticks.
   //
   // Presentation time stamps on audio packets are expressed in units of media
diff --git a/mojo/services/media/common/cpp/circular_buffer_media_pipe_adapter.cc b/mojo/services/media/common/cpp/circular_buffer_media_pipe_adapter.cc
index 4ce301f..406c50a 100644
--- a/mojo/services/media/common/cpp/circular_buffer_media_pipe_adapter.cc
+++ b/mojo/services/media/common/cpp/circular_buffer_media_pipe_adapter.cc
@@ -39,11 +39,6 @@
   MOJO_DCHECK(pipe_);
   MOJO_DCHECK(RunLoop::current());
 
-  pipe_get_state_cbk_ = MediaPipe::GetStateCallback(
-  [this] (MediaPipeStatePtr state) {
-    HandleGetState(state.Pass());
-  });
-
   pipe_flush_cbk_ = MediaPipe::FlushCallback(
   [this] () {
     HandleFlush();
@@ -61,12 +56,6 @@
       (*thiz)->HandleSignalCallback();
     }
   });
-
-
-  // Begin by getting a hold of the shared buffer from our pipe over which we
-  // will push data.
-  MOJO_DCHECK(get_state_in_progress_);
-  pipe_->GetState(pipe_get_state_cbk_);
 }
 
 CircularBufferMediaPipeAdapter::~CircularBufferMediaPipeAdapter() {
@@ -74,6 +63,63 @@
   Cleanup();
 }
 
+void CircularBufferMediaPipeAdapter::Init(uint64_t size) {
+  // Double Init?  Fault unless the user is asking us to set up a buffer of the
+  // same size.
+  if (buffer_handle_.is_valid()) {
+    if (buffer_size_ != size) {
+      Fault(MediaResult::BAD_STATE);
+    }
+    return;
+  }
+
+  // Make the buffer
+  MojoResult res = CreateSharedBuffer(nullptr, size, &buffer_handle_);
+  if (res != MOJO_RESULT_OK) {
+    MOJO_LOG(ERROR) << "Failed to allocate buffer of size " << size
+                    << " in " << __PRETTY_FUNCTION__
+                    << " (error " << res << ")";
+    Fault(MediaResult::INSUFFICIENT_RESOURCES);
+    return;
+  }
+
+  buffer_size_ = size;
+
+  // Map the buffer
+  //
+  // TODO(johngro) : We really only need write access to this buffer.
+  // Ideally, we could request that using flags, but there does not seem to be
+  // a way to do this right now.
+  res = MapBuffer(buffer_handle_.get(),
+                  0,
+                  buffer_size_,
+                  &buffer_,
+                  MOJO_MAP_BUFFER_FLAG_NONE);
+  if (res != MOJO_RESULT_OK) {
+    MOJO_LOG(ERROR) << "Failed to map buffer in " << __PRETTY_FUNCTION__
+                    << " (error " << res << ")";
+    Fault(MediaResult::UNKNOWN_ERROR);
+    return;
+  }
+
+  // Duplicate the buffer and send it to the other side of the pipe.
+  //
+  // TODO(johngro) : It would be nice if we could restrict this handle to be
+  // read-only.
+  ScopedSharedBufferHandle duplicated_handle;
+  res = DuplicateBuffer(buffer_handle_.get(), nullptr, &duplicated_handle);
+  if (res != MOJO_RESULT_OK) {
+    MOJO_LOG(ERROR) << "Failed to duplicate handle in " << __PRETTY_FUNCTION__
+                    << " (error " << res << ")";
+    Fault(MediaResult::UNKNOWN_ERROR);
+    return;
+  }
+
+  // TODO(johngro) : We should not have to send the buffer size, it should be an
+  // intrinsic property of the buffer itself and be query-able via the handle.
+  pipe_->SetBuffer(duplicated_handle.Pass(), buffer_size_);
+}
+
 void CircularBufferMediaPipeAdapter::SetSignalCallback(SignalCbk cbk) {
   bool schedule;
   signal_cbk_ = cbk;
@@ -298,78 +344,12 @@
   return MediaResult::OK;
 }
 
-void CircularBufferMediaPipeAdapter::HandleGetState(MediaPipeStatePtr state) {
-  MOJO_DCHECK(state);     // We must have a state structure.
-  MOJO_DCHECK(!buffer_);  // We must not have already mapped a buffer.
-  MOJO_DCHECK(get_state_in_progress_);  // We should be waiting for our cbk.
-
-  // Success or failure, we are no longer waiting for our get state callback.
-  get_state_in_progress_ = false;
-  rd_ = wr_ = 0;
-
-  // Double init?  How did that happen?
-  if (buffer_handle_.is_valid() || (nullptr != buffer_)) {
-    MOJO_LOG(ERROR) << "Double init during " << __PRETTY_FUNCTION__;
-    Fault(MediaResult::UNKNOWN_ERROR);
-    return;
-  }
-
-  // No shared buffer?  That's a fatal error.
-  if (!state->payload_buffer.is_valid()) {
-    MOJO_LOG(ERROR) << "Null payload buffer in " << __PRETTY_FUNCTION__;
-    Fault(MediaResult::UNKNOWN_ERROR);
-    return;
-  }
-
-  // stash our state
-  buffer_handle_ = state->payload_buffer.Pass();
-  buffer_size_   = state->payload_buffer_len;
-
-  // Sanity checks the buffer size.
-  if (!buffer_size_ || (buffer_size_ > MediaPipeState::kMaxPayloadLen)) {
-    MOJO_LOG(ERROR) << "Bad buffer size in " << __PRETTY_FUNCTION__
-               << " (" << buffer_size_ << ")";
-    Fault(MediaResult::BAD_STATE);
-    return;
-  }
-
-  // Map our buffer
-  //
-  // TODO(johngro) : We really only need write access to this buffer.
-  // Ideally, we could request that using flags, but there does not seem to be
-  // a way to do this right now.
-  MojoResult res;
-  res = MapBuffer(buffer_handle_.get(),
-                  0,
-                  buffer_size_,
-                  &buffer_,
-                  MOJO_MAP_BUFFER_FLAG_NONE);
-  if (res != MOJO_RESULT_OK) {
-    MOJO_LOG(ERROR) << "Failed to map buffer in " << __PRETTY_FUNCTION__
-               << " (error " << res << ")";
-    Fault(MediaResult::UNKNOWN_ERROR);
-    return;
-  }
-
-  // Init is complete, we may be signalled now.
-  UpdateSignalled();
-}
-
 void CircularBufferMediaPipeAdapter::HandleSendPacket(
     uint32_t seq_num,
     MediaPipe::SendResult result) {
   MediaPipe::SendPacketCallback cbk;
 
   do {
-    if (get_state_in_progress_) {
-      // If we are in the process of getting the initial state of the system,
-      // then something is seriously wrong.  The other end of this interface is
-      // sending us Send callbacks while we are in the process of initializing
-      // (something which should be impossible)
-      Fault(MediaResult::PROTOCOL_ERROR);
-      break;
-    }
-
     // There should be at least one element in the in-flight queue, and the
     // front of the queue's sequence number should match the sequence number of
     // the payload being returned to us.
diff --git a/mojo/services/media/common/cpp/circular_buffer_media_pipe_adapter.h b/mojo/services/media/common/cpp/circular_buffer_media_pipe_adapter.h
index 73fe68d..679b624 100644
--- a/mojo/services/media/common/cpp/circular_buffer_media_pipe_adapter.h
+++ b/mojo/services/media/common/cpp/circular_buffer_media_pipe_adapter.h
@@ -70,10 +70,34 @@
    */
   using SignalCbk = std::function<void(MediaResult state)>;
 
+  /**
+   * Constructor
+   *
+   * Create an adapter which will take ownership of the provided MediaPipe
+   * interface and assist in the process of generating MediaPackets and
+   * marshalling them to the other side of the MediaPipe.
+   *
+   * @param pipe A pointer to the MediaPipe interface which will be used as the
+   * target for MediaPackets.
+   */
   explicit CircularBufferMediaPipeAdapter(MediaPipePtr pipe);
+
+  /**
+   * Destructor
+   */
   ~CircularBufferMediaPipeAdapter();
 
   /**
+   * Init
+   *
+   * Allocate a shared memory buffer of the specified size and begin the process
+   * of marshalling it to the other side of the MediaPipe.
+   *
+   * @param size The size in bytes of the shared memory buffer to allocate.
+   */
+  void Init(uint64_t size);
+
+  /**
    * Set the signal callback for this media pipe adapter.  This callback will be
    * called when the adapter transitions from un-signalled to signalled and has
    * a valid callback, or when a valid callback is assigned (via a call to
@@ -205,7 +229,6 @@
   };
   using PacketStateQueue = std::deque<PacketState>;
 
-  void HandleGetState(MediaPipeStatePtr state);
   void HandleSendPacket(uint32_t seq_num, MediaPipe::SendResult result);
   void HandleFlush();
   void HandleSignalCallback();
@@ -219,12 +242,11 @@
   }
 
   bool Busy() const {
-    return (get_state_in_progress_ || flush_in_progress_);
+    return flush_in_progress_;
   }
 
   // Pipe interface callbacks
   MediaPipePtr pipe_;
-  MediaPipe::GetStateCallback pipe_get_state_cbk_;
   MediaPipe::FlushCallback    pipe_flush_cbk_;
   Closure                     signalled_callback_;
 
@@ -234,7 +256,6 @@
 
   // State for managing signalled/un-signalled status and signal callbacks.
   SignalCbk signal_cbk_;
-  bool      get_state_in_progress_ = true;
   bool      flush_in_progress_ = false;
   bool      fault_cbk_made_ = false;
   bool      cbk_scheduled_ = false;
@@ -246,7 +267,7 @@
 
   ScopedSharedBufferHandle buffer_handle_;
   void*    buffer_ = nullptr;
-  uint64_t buffer_size_;
+  uint64_t buffer_size_ = 0;
   uint64_t rd_, wr_;
 
   // Packet queue state
diff --git a/mojo/services/media/common/interfaces/media_pipe.mojom b/mojo/services/media/common/interfaces/media_pipe.mojom
index ca5e400..7efbd2f 100644
--- a/mojo/services/media/common/interfaces/media_pipe.mojom
+++ b/mojo/services/media/common/interfaces/media_pipe.mojom
@@ -61,25 +61,6 @@
   // packet?
 };
 
-// MediaPipeState
-//
-// A small structure used by the user of a media pipe to fetch the shared buffer
-// used by the media pipe to move bulk data.
-//
-// TODO(johngro): Right now, the only real purpose for this struture is to
-// bundle the size of the buffer with the buffer handle itself.  When buffer
-// handles can have their properties queried directly, it can go away.  See
-// domokit/mojo issue #501
-struct MediaPipeState {
-  const uint64 kMaxPayloadLen = 0x3FFFFFFFFFFFFFFF;
-
-  handle<shared_buffer> payload_buffer;
-
-  // TODO(johngro) : Why do I have to send this?  Why can't I just query the
-  // shared_buffer handle for its length?
-  uint64 payload_buffer_len;
-};
-
 // MediaPipe
 //
 // An interface exposed by consumers of media which provides the means for
@@ -90,6 +71,8 @@
 // the media has been consumed via the SendPacket callback they provide.
 // Finally, the pipeline may be flushed using the Flush method.
 interface MediaPipe {
+  const uint64 kMaxBufferLen = 0x3FFFFFFFFFFFFFFF;
+
   // An enumeration used to indicate the ultimate fate of packets sent across
   // the pipe using the SendPacket method.
   enum SendResult {
@@ -97,9 +80,8 @@
     FLUSHED,   // Some or all of the media was flushed before being consumed.
   };
 
-  // Request that a reference to the pipe's state be sent to the caller via
-  // callback.
-  GetState() => (MediaPipeState state);
+  // Sets the shared buffer in which sent Packet payloads will be located.
+  SetBuffer(handle<shared_buffer> buffer, uint64 size);
 
   // Place a media packet into the pipeline to be consumed.  When the consumer
   // is finished with the packet, it will invoke the supplied callback to
diff --git a/services/media/audio/audio_track_impl.cc b/services/media/audio/audio_track_impl.cc
index 84ecf25..a12c3af 100644
--- a/services/media/audio/audio_track_impl.cc
+++ b/services/media/audio/audio_track_impl.cc
@@ -225,23 +225,9 @@
   }
   bytes_per_frame_ *= cfg->channels;
 
-  // Overflow trying to convert from frames to bytes?
-  uint64_t requested_frames = configuration->max_frames;
-  if (requested_frames >
-     (std::numeric_limits<size_t>::max() / bytes_per_frame_)) {
-    LOG(ERROR) << "Insufficient resources to create "
-               << requested_frames << " frame audio buffer.";
-    Shutdown();
-    return;
-  }
-
-  size_t requested_bytes = (requested_frames * bytes_per_frame_);
-
-  // Attempt to initialize our shared buffer and bind it to our interface
-  // request.
-  if (pipe_.Init(req.Pass(), requested_bytes) != MOJO_RESULT_OK) {
-    LOG(ERROR) << "Insufficient resources to create "
-               << requested_frames << " frame audio buffer.";
+  // Bind our pipe to the interface request.
+  if (pipe_.Init(req.Pass()) != MOJO_RESULT_OK) {
+    LOG(ERROR) << "Failed to media pipe to interface request.";
     Shutdown();
     return;
   }
diff --git a/services/media/common/media_pipe_base.cc b/services/media/common/media_pipe_base.cc
index 642c686..4a7df2d 100644
--- a/services/media/common/media_pipe_base.cc
+++ b/services/media/common/media_pipe_base.cc
@@ -15,27 +15,12 @@
 MediaPipeBase::~MediaPipeBase() {
 }
 
-MojoResult MediaPipeBase::Init(InterfaceRequest<MediaPipe> request,
-                               uint64_t shared_buffer_size) {
+MojoResult MediaPipeBase::Init(InterfaceRequest<MediaPipe> request) {
   // Double init?
   if (IsInitialized()) {
     return MOJO_RESULT_ALREADY_EXISTS;
   }
 
-  // Valid size?
-  DCHECK_GT(shared_buffer_size, 0u);
-  DCHECK_LE(shared_buffer_size, MediaPipeState::kMaxPayloadLen);
-  if (!shared_buffer_size ||
-      (shared_buffer_size > MediaPipeState::kMaxPayloadLen)) {
-    return MOJO_RESULT_INVALID_ARGUMENT;
-  }
-
-  DCHECK(!buffer_);
-  buffer_ = MappedSharedBuffer::Create(shared_buffer_size);
-  if (buffer_ == nullptr) {
-    return MOJO_RESULT_UNKNOWN;
-  }
-
   binding_.Bind(request.Pass());
   binding_.set_connection_error_handler([this]() -> void {
     Reset();
@@ -44,9 +29,7 @@
 }
 
 bool MediaPipeBase::IsInitialized() const {
-  DCHECK((!binding_.is_bound() && (buffer_ == nullptr)) ||
-          (binding_.is_bound() && (buffer_ != nullptr)));
-  return !!buffer_;
+  return binding_.is_bound();
 }
 
 void MediaPipeBase::Reset() {
@@ -56,27 +39,33 @@
   buffer_ = nullptr;
 }
 
-void MediaPipeBase::GetState(const GetStateCallback& cbk) {
-  static const MojoDuplicateBufferHandleOptions options = {
-    .struct_size = sizeof(*this),
-    .flags = MOJO_DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_NONE,
-  };
-
-  MediaPipeStatePtr state_ptr(MediaPipeState::New());
-
-  // If we have not been successfully initialized, send back an invalid handle
-  // and a zero length.
-  if (!buffer_) {
-    state_ptr->payload_buffer_len = 0;
-  } else {
-    MojoResult res = DuplicateBuffer(buffer_->handle().get(),
-                                     &options,
-                                     &state_ptr->payload_buffer);
-    state_ptr->payload_buffer_len = buffer_->size();
-    DCHECK(MOJO_RESULT_OK == res);
+void MediaPipeBase::SetBuffer(ScopedSharedBufferHandle handle, uint64_t size) {
+  // Double init?  Close the connection.
+  if (buffer_) {
+    LOG(ERROR) << "Attempting to set a new buffer (size = "
+               << size
+               << ") on a MediaPipe which already has a buffer (size = "
+               << buffer_->size()
+               << ")";
+    Reset();
+    return;
   }
 
-  cbk.Run(state_ptr.Pass());
+  // Invalid size?  Close the connection.
+  if (!size || (size > MediaPipe::kMaxBufferLen)) {
+    LOG(ERROR) << "Invalid shared buffer size (size = " << size << ")";
+    Reset();
+    return;
+  }
+
+
+  // Failed to map the buffer?  Close the connection.
+  buffer_ = MappedSharedBuffer::Create(handle.Pass(), size);
+  if (!buffer_) {
+    LOG(ERROR) << "Failed to map shared memory buffer (size = " << size << ")";
+    Reset();
+    return;
+  }
 }
 
 void MediaPipeBase::SendPacket(MediaPacketPtr packet,
@@ -167,8 +156,9 @@
 }
 
 MediaPipeBase::MappedSharedBufferPtr MediaPipeBase::MappedSharedBuffer::Create(
-    size_t size) {
-  MappedSharedBufferPtr ret(new MappedSharedBuffer(size));
+    ScopedSharedBufferHandle handle,
+    uint64_t size) {
+  MappedSharedBufferPtr ret(new MappedSharedBuffer(handle.Pass(), size));
   return ret->base() ? ret : nullptr;
 }
 
@@ -179,35 +169,22 @@
   }
 }
 
-MediaPipeBase::MappedSharedBuffer::MappedSharedBuffer(size_t size)
-  : size_(size) {
-  static const MojoCreateSharedBufferOptions opt {
-    .struct_size = sizeof(MojoDuplicateBufferHandleOptions),
-    .flags = MOJO_CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE,
-  };
-  MojoResult res;
+MediaPipeBase::MappedSharedBuffer::MappedSharedBuffer(
+    ScopedSharedBufferHandle handle,
+    size_t size)
+  : handle_(handle.Pass()),
+    size_(size) {
+  MojoResult res = MapBuffer(handle_.get(),
+                             0u,
+                             size_,
+                             &base_,
+                             MOJO_MAP_BUFFER_FLAG_NONE);
 
-  res = CreateSharedBuffer(&opt, size_, &handle_);
-  if (MOJO_RESULT_OK == res) {
-    // TODO(johngro) : We really only need read access to this buffer.  Ideally,
-    // we could request that using flags, but there does not seem to be a way to
-    // do this right now.
-    res = MapBuffer(handle_.get(),
-                    0u,
-                    size_,
-                    &base_,
-                    MOJO_MAP_BUFFER_FLAG_NONE);
-
-    if (MOJO_RESULT_OK != res) {
-      LOG(ERROR) << "Failed to map shared buffer of size " << size_
-                 << " (res " << res << ")";
-      DCHECK(base_ == nullptr);
-      handle_.reset();
-    }
-  } else {
-    LOG(ERROR) << "Failed to create shared buffer of size " << size_
+  if (MOJO_RESULT_OK != res) {
+    LOG(ERROR) << "Failed to map shared buffer of size " << size_
                << " (res " << res << ")";
-    DCHECK(!handle_.is_valid());
+    DCHECK(base_ == nullptr);
+    handle_.reset();
   }
 }
 
diff --git a/services/media/common/media_pipe_base.h b/services/media/common/media_pipe_base.h
index 07bea65..9e7499f 100644
--- a/services/media/common/media_pipe_base.h
+++ b/services/media/common/media_pipe_base.h
@@ -50,8 +50,7 @@
   ~MediaPipeBase() override;
 
   // Initialize the internal state of the pipe (allocate resources, etc..)
-  MojoResult Init(InterfaceRequest<MediaPipe> request,
-                  uint64_t shared_buffer_size);
+  MojoResult Init(InterfaceRequest<MediaPipe> request);
 
   bool IsInitialized() const;
   void Reset();
@@ -59,15 +58,16 @@
  protected:
   class MappedSharedBuffer {
    public:
-    static MappedSharedBufferPtr Create(size_t size);
+    static MappedSharedBufferPtr Create(ScopedSharedBufferHandle handle,
+                                        uint64_t size);
     ~MappedSharedBuffer();
 
     const ScopedSharedBufferHandle& handle() const { return handle_; }
-    size_t size() const { return size_; }
-    void*  base() const { return base_; }
+    uint64_t size() const { return size_; }
+    void*    base() const { return base_; }
 
    private:
-    explicit MappedSharedBuffer(size_t size);
+    MappedSharedBuffer(ScopedSharedBufferHandle handle, size_t size);
 
     ScopedSharedBufferHandle handle_;
     size_t size_;
@@ -84,7 +84,7 @@
   Binding<MediaPipe> binding_;
 
   // MediaPipe.mojom implementation.
-  void GetState(const GetStateCallback& cbk) final;
+  void SetBuffer(ScopedSharedBufferHandle handle, uint64_t size) final;
   void SendPacket(MediaPacketPtr packet,
                   const SendPacketCallback& cbk) final;
   void Flush(const FlushCallback& cbk) final;