| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "base/logging.h" | 5 #include "base/logging.h" |
| 6 #include "services/media/factory_service/media_sink_impl.h" | 6 #include "services/media/factory_service/media_sink_impl.h" |
| 7 #include "services/media/framework/util/conversion_pipeline_builder.h" | 7 #include "services/media/framework/util/conversion_pipeline_builder.h" |
| 8 #include "services/media/framework_mojo/mojo_type_conversions.h" | 8 #include "services/media/framework_mojo/mojo_type_conversions.h" |
| 9 | 9 |
| 10 namespace mojo { | 10 namespace mojo { |
| 11 namespace media { | 11 namespace media { |
| 12 | 12 |
| 13 // static | 13 // static |
| 14 std::shared_ptr<MediaSinkImpl> MediaSinkImpl::Create( | 14 std::shared_ptr<MediaSinkImpl> MediaSinkImpl::Create( |
| 15 const String& destination_url, | 15 InterfaceHandle<MediaRenderer> renderer, |
| 16 MediaTypePtr media_type, | 16 MediaTypePtr media_type, |
| 17 InterfaceRequest<MediaSink> request, | 17 InterfaceRequest<MediaSink> request, |
| 18 MediaFactoryService* owner) { | 18 MediaFactoryService* owner) { |
| 19 return std::shared_ptr<MediaSinkImpl>(new MediaSinkImpl( | 19 return std::shared_ptr<MediaSinkImpl>(new MediaSinkImpl( |
| 20 destination_url, media_type.Pass(), request.Pass(), owner)); | 20 renderer.Pass(), media_type.Pass(), request.Pass(), owner)); |
| 21 } | 21 } |
| 22 | 22 |
| 23 MediaSinkImpl::MediaSinkImpl(const String& destination_url, | 23 MediaSinkImpl::MediaSinkImpl(InterfaceHandle<MediaRenderer> renderer, |
| 24 MediaTypePtr media_type, | 24 MediaTypePtr media_type, |
| 25 InterfaceRequest<MediaSink> request, | 25 InterfaceRequest<MediaSink> request, |
| 26 MediaFactoryService* owner) | 26 MediaFactoryService* owner) |
| 27 : MediaFactoryService::Product<MediaSink>(this, request.Pass(), owner), | 27 : MediaFactoryService::Product<MediaSink>(this, request.Pass(), owner), |
| 28 consumer_(MojoConsumer::Create()), | 28 consumer_(MojoConsumer::Create()), |
| 29 producer_(MojoProducer::Create()) { | 29 producer_(MojoProducer::Create()), |
| 30 DCHECK(destination_url); | 30 renderer_(MediaRendererPtr::Create(renderer.Pass())) { |
| 31 DCHECK(media_type); | 31 DCHECK(media_type); |
| 32 | 32 |
| 33 PartRef consumer_ref = graph_.Add(consumer_); | 33 PartRef consumer_ref = graph_.Add(consumer_); |
| 34 PartRef producer_ref = graph_.Add(producer_); | 34 PartRef producer_ref = graph_.Add(producer_); |
| 35 | 35 |
| 36 consumer_->SetPrimeRequestedCallback( | 36 consumer_->SetPrimeRequestedCallback( |
| 37 [this](const MediaConsumer::PrimeCallback& callback) { | 37 [this](const MediaConsumer::PrimeCallback& callback) { |
| 38 ready_.When([this, callback]() { | 38 ready_.When([this, callback]() { |
| 39 DCHECK(producer_); | 39 DCHECK(producer_); |
| 40 producer_->PrimeConnection(callback); | 40 producer_->PrimeConnection(callback); |
| 41 }); | 41 }); |
| 42 }); | 42 }); |
| 43 consumer_->SetFlushRequestedCallback( | 43 consumer_->SetFlushRequestedCallback( |
| 44 [this, consumer_ref](const MediaConsumer::FlushCallback& callback) { | 44 [this, consumer_ref](const MediaConsumer::FlushCallback& callback) { |
| 45 ready_.When([this, consumer_ref, callback]() { | 45 ready_.When([this, consumer_ref, callback]() { |
| 46 DCHECK(producer_); | 46 DCHECK(producer_); |
| 47 graph_.FlushOutput(consumer_ref.output()); | 47 graph_.FlushOutput(consumer_ref.output()); |
| 48 producer_->FlushConnection(callback); | 48 producer_->FlushConnection(callback); |
| 49 }); | 49 }); |
| 50 }); | 50 }); |
| 51 | 51 |
| 52 // TODO(dalesat): Temporary, remove. | 52 // TODO(dalesat): Temporary, remove. |
| 53 if (destination_url == "nowhere") { | 53 if (!renderer_) { |
| 54 // Throwing away the content. | 54 // Throwing away the content. |
| 55 graph_.ConnectParts(consumer_ref, producer_ref); | 55 graph_.ConnectParts(consumer_ref, producer_ref); |
| 56 graph_.Prepare(); | 56 graph_.Prepare(); |
| 57 ready_.Occur(); | 57 ready_.Occur(); |
| 58 return; | 58 return; |
| 59 } | 59 } |
| 60 | 60 |
| 61 RCHECK(destination_url == "mojo:audio_server"); | 61 // TODO(dalesat): Once we have c++14, get rid of this shared pointer hack. |
| 62 input_stream_type_ = media_type.To<std::unique_ptr<StreamType>>(); |
| 62 | 63 |
| 63 // TODO(dalesat): Once we have c++14, get rid of this shared pointer hack. | 64 renderer_->GetSupportedMediaTypes([this, consumer_ref, producer_ref]( |
| 64 std::shared_ptr<StreamType> captured_stream_type( | 65 Array<MediaTypeSetPtr> supported_media_types) { |
| 65 media_type.To<std::unique_ptr<StreamType>>().release()); | 66 std::unique_ptr<std::vector<std::unique_ptr<StreamTypeSet>>> |
| 66 | 67 supported_stream_types = supported_media_types.To<std::unique_ptr< |
| 67 // An AudioTrackController knows how to talk to an audio track, interrogating | 68 std::vector<std::unique_ptr<media::StreamTypeSet>>>>(); |
| 68 // it for supported stream types and configuring it for the chosen stream | |
| 69 // type. | |
| 70 controller_.reset(new AudioTrackController(destination_url, owner->shell())); | |
| 71 | |
| 72 controller_->GetSupportedMediaTypes([this, consumer_ref, producer_ref, | |
| 73 captured_stream_type]( | |
| 74 std::unique_ptr<std::vector<std::unique_ptr<StreamTypeSet>>> | |
| 75 supported_stream_types) { | |
| 76 std::unique_ptr<StreamType> producer_stream_type; | 69 std::unique_ptr<StreamType> producer_stream_type; |
| 77 | 70 |
| 78 // Add transforms to the pipeline to convert from stream_type to a | 71 // Add transforms to the pipeline to convert from stream_type to a |
| 79 // type supported by the track. | 72 // type supported by the track. |
| 80 OutputRef out = consumer_ref.output(); | 73 OutputRef out = consumer_ref.output(); |
| 81 bool result = | 74 bool result = |
| 82 BuildConversionPipeline(*captured_stream_type, *supported_stream_types, | 75 BuildConversionPipeline(*input_stream_type_, *supported_stream_types, |
| 83 &graph_, &out, &producer_stream_type); | 76 &graph_, &out, &producer_stream_type); |
| 84 if (!result) { | 77 if (!result) { |
| 85 // Failed to build conversion pipeline. | 78 // Failed to build conversion pipeline. |
| 86 LOG(WARNING) << "failed to build conversion pipeline"; | 79 LOG(WARNING) << "failed to build conversion pipeline"; |
| 87 // TODO(dalesat): Add problem reporting. | 80 // TODO(dalesat): Add problem reporting. |
| 88 return; | 81 return; |
| 89 } | 82 } |
| 90 | 83 |
| 91 graph_.ConnectOutputToPart(out, producer_ref); | 84 graph_.ConnectOutputToPart(out, producer_ref); |
| 92 | 85 |
| 93 controller_->Configure(std::move(producer_stream_type), | 86 renderer_->SetMediaType(MediaType::From(std::move(producer_stream_type))); |
| 94 [this](MediaConsumerPtr consumer) { | 87 MediaConsumerPtr consumer; |
| 95 DCHECK(consumer); | 88 renderer_->GetConsumer(GetProxy(&consumer)); |
| 96 producer_->Connect(consumer.Pass(), [this]() { | 89 producer_->Connect(consumer.Pass(), [this]() { |
| 97 graph_.Prepare(); | 90 graph_.Prepare(); |
| 98 ready_.Occur(); | 91 ready_.Occur(); |
| 99 }); | 92 }); |
| 100 }); | |
| 101 }); | 93 }); |
| 102 } | 94 } |
| 103 | 95 |
| 104 MediaSinkImpl::~MediaSinkImpl() {} | 96 MediaSinkImpl::~MediaSinkImpl() {} |
| 105 | 97 |
| 106 void MediaSinkImpl::GetConsumer(InterfaceRequest<MediaConsumer> consumer) { | 98 void MediaSinkImpl::GetConsumer(InterfaceRequest<MediaConsumer> consumer) { |
| 107 consumer_->AddBinding(consumer.Pass()); | 99 consumer_->AddBinding(consumer.Pass()); |
| 108 } | 100 } |
| 109 | 101 |
| 110 void MediaSinkImpl::GetTimelineControlSite( | 102 void MediaSinkImpl::GetTimelineControlSite( |
| 111 InterfaceRequest<MediaTimelineControlSite> req) { | 103 InterfaceRequest<MediaTimelineControlSite> req) { |
| 112 if (!controller_) { | 104 if (renderer_) { |
| 113 LOG(ERROR) << "GetTimelineControlSite not implemented for 'nowhere' case"; | 105 renderer_->GetTimelineControlSite(req.Pass()); |
| 114 abort(); | 106 return; |
| 115 } | 107 } |
| 116 controller_->GetTimelineControlSite(req.Pass()); | 108 |
| 109 new NullTimelineControlSite(req.Pass()); |
| 110 } |
| 111 |
| 112 MediaSinkImpl::NullTimelineControlSite::NullTimelineControlSite( |
| 113 InterfaceRequest<MediaTimelineControlSite> control_site_request) |
| 114 : control_site_binding_(this, control_site_request.Pass()), |
| 115 consumer_binding_(this) {} |
| 116 |
| 117 MediaSinkImpl::NullTimelineControlSite::~NullTimelineControlSite() {} |
| 118 |
| 119 void MediaSinkImpl::NullTimelineControlSite::GetStatus( |
| 120 uint64_t version_last_seen, |
| 121 const GetStatusCallback& callback) { |
| 122 DCHECK(get_status_callback_.is_null()); |
| 123 get_status_callback_ = callback; |
| 124 } |
| 125 |
| 126 void MediaSinkImpl::NullTimelineControlSite::GetTimelineConsumer( |
| 127 InterfaceRequest<TimelineConsumer> timeline_consumer) { |
| 128 consumer_binding_.Bind(timeline_consumer.Pass()); |
| 129 } |
| 130 |
| 131 void MediaSinkImpl::NullTimelineControlSite::SetTimelineTransform( |
| 132 int64_t subject_time, |
| 133 uint32_t reference_delta, |
| 134 uint32_t subject_delta, |
| 135 int64_t effective_reference_time, |
| 136 int64_t effective_subject_time, |
| 137 const SetTimelineTransformCallback& callback) { |
| 138 callback.Run(true); |
| 117 } | 139 } |
| 118 | 140 |
| 119 } // namespace media | 141 } // namespace media |
| 120 } // namespace mojo | 142 } // namespace mojo |
| OLD | NEW |