Thu, 15 Jan 2015 15:59:08 +0100
Implement a real Private Browsing Mode condition by changing the API/ABI;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
4 * You can obtain one at http://mozilla.org/MPL/2.0/. */
6 // Original author: ekr@rtfm.com
8 #ifndef mediapipeline_h__
9 #define mediapipeline_h__
11 #include "sigslot.h"
13 #ifdef USE_FAKE_MEDIA_STREAMS
14 #include "FakeMediaStreams.h"
15 #else
16 #include "DOMMediaStream.h"
17 #include "MediaStreamGraph.h"
18 #include "VideoUtils.h"
19 #endif
20 #include "MediaConduitInterface.h"
21 #include "MediaPipelineFilter.h"
22 #include "AudioSegment.h"
23 #include "mozilla/ReentrantMonitor.h"
24 #include "SrtpFlow.h"
25 #include "databuffer.h"
26 #include "runnable_utils.h"
27 #include "transportflow.h"
29 #ifdef MOZILLA_INTERNAL_API
30 #include "VideoSegment.h"
31 #endif
33 #include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h"
35 namespace mozilla {
37 // A class that represents the pipeline of audio and video
38 // The dataflow looks like:
39 //
40 // TRANSMIT
41 // CaptureDevice -> stream -> [us] -> conduit -> [us] -> transport -> network
42 //
43 // RECEIVE
44 // network -> transport -> [us] -> conduit -> [us] -> stream -> Playout
45 //
46 // The boxes labeled [us] are just bridge logic implemented in this class
47 //
48 // We have to deal with a number of threads:
49 //
50 // GSM:
51 // * Assembles the pipeline
52 // SocketTransportService
53 // * Receives notification that ICE and DTLS have completed
54 // * Processes incoming network data and passes it to the conduit
55 // * Processes outgoing RTP and RTCP
56 // MediaStreamGraph
57 // * Receives outgoing data from the MediaStreamGraph
58 // * Receives pull requests for more data from the
59 // MediaStreamGraph
60 // One or another GIPS threads
61 // * Receives RTCP messages to send to the other side
62 // * Processes video frames GIPS wants to render
63 //
64 // For a transmitting conduit, "output" is RTP and "input" is RTCP.
65 // For a receiving conduit, "input" is RTP and "output" is RTCP.
66 //
67 class MediaPipeline : public sigslot::has_slots<> {
68 public:
69 enum Direction { TRANSMIT, RECEIVE };
70 enum State { MP_CONNECTING, MP_OPEN, MP_CLOSED };
71 MediaPipeline(const std::string& pc,
72 Direction direction,
73 nsCOMPtr<nsIEventTarget> main_thread,
74 nsCOMPtr<nsIEventTarget> sts_thread,
75 MediaStream *stream,
76 TrackID track_id,
77 int level,
78 RefPtr<MediaSessionConduit> conduit,
79 RefPtr<TransportFlow> rtp_transport,
80 RefPtr<TransportFlow> rtcp_transport)
81 : direction_(direction),
82 stream_(stream),
83 track_id_(track_id),
84 level_(level),
85 conduit_(conduit),
86 rtp_(rtp_transport, rtcp_transport ? RTP : MUX),
87 rtcp_(rtcp_transport ? rtcp_transport : rtp_transport,
88 rtcp_transport ? RTCP : MUX),
89 main_thread_(main_thread),
90 sts_thread_(sts_thread),
91 rtp_packets_sent_(0),
92 rtcp_packets_sent_(0),
93 rtp_packets_received_(0),
94 rtcp_packets_received_(0),
95 rtp_bytes_sent_(0),
96 rtp_bytes_received_(0),
97 pc_(pc),
98 description_() {
99 // To indicate rtcp-mux rtcp_transport should be nullptr.
100 // Therefore it's an error to send in the same flow for
101 // both rtp and rtcp.
102 MOZ_ASSERT(rtp_transport != rtcp_transport);
104 // PipelineTransport() will access this->sts_thread_; moved here for safety
105 transport_ = new PipelineTransport(this);
106 }
108 virtual ~MediaPipeline();
110 // Must be called on the STS thread. Must be called after ShutdownMedia_m().
111 void ShutdownTransport_s();
113 // Must be called on the main thread.
114 void ShutdownMedia_m() {
115 ASSERT_ON_THREAD(main_thread_);
117 if (stream_) {
118 DetachMediaStream();
119 }
120 }
122 virtual nsresult Init();
124 // When we have offered bundle, the MediaPipelines are created in an
125 // indeterminate state; we do not know whether the answerer will take us
126 // up on our offer. In the meantime, we need to behave in a manner that
127 // errs on the side of packet loss when it is unclear whether an arriving
128 // packet is meant for us. We want to get out of this indeterminate state
129 // ASAP, which is what this function can be used for.
130 void SetUsingBundle_s(bool decision);
131 MediaPipelineFilter* UpdateFilterFromRemoteDescription_s(
132 nsAutoPtr<MediaPipelineFilter> filter);
134 virtual Direction direction() const { return direction_; }
135 virtual TrackID trackid() const { return track_id_; }
136 virtual int level() const { return level_; }
138 bool IsDoingRtcpMux() const {
139 return (rtp_.type_ == MUX);
140 }
142 int32_t rtp_packets_sent() const { return rtp_packets_sent_; }
143 int64_t rtp_bytes_sent() const { return rtp_bytes_sent_; }
144 int32_t rtcp_packets_sent() const { return rtcp_packets_sent_; }
145 int32_t rtp_packets_received() const { return rtp_packets_received_; }
146 int64_t rtp_bytes_received() const { return rtp_bytes_received_; }
147 int32_t rtcp_packets_received() const { return rtcp_packets_received_; }
149 MediaSessionConduit *Conduit() const { return conduit_; }
151 // Thread counting
152 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaPipeline)
154 typedef enum {
155 RTP,
156 RTCP,
157 MUX,
158 MAX_RTP_TYPE
159 } RtpType;
161 protected:
162 virtual void DetachMediaStream() {}
164 // Separate class to allow ref counting
165 class PipelineTransport : public TransportInterface {
166 public:
167 // Implement the TransportInterface functions
168 explicit PipelineTransport(MediaPipeline *pipeline)
169 : pipeline_(pipeline),
170 sts_thread_(pipeline->sts_thread_) {}
172 void Detach() { pipeline_ = nullptr; }
173 MediaPipeline *pipeline() const { return pipeline_; }
175 virtual nsresult SendRtpPacket(const void* data, int len);
176 virtual nsresult SendRtcpPacket(const void* data, int len);
178 private:
179 virtual nsresult SendRtpPacket_s(nsAutoPtr<DataBuffer> data);
180 virtual nsresult SendRtcpPacket_s(nsAutoPtr<DataBuffer> data);
182 MediaPipeline *pipeline_; // Raw pointer to avoid cycles
183 nsCOMPtr<nsIEventTarget> sts_thread_;
184 };
185 friend class PipelineTransport;
187 class TransportInfo {
188 public:
189 TransportInfo(RefPtr<TransportFlow> flow, RtpType type) :
190 transport_(flow),
191 state_(MP_CONNECTING),
192 type_(type) {
193 MOZ_ASSERT(flow);
194 }
196 RefPtr<TransportFlow> transport_;
197 State state_;
198 RefPtr<SrtpFlow> send_srtp_;
199 RefPtr<SrtpFlow> recv_srtp_;
200 RtpType type_;
201 };
203 // The transport is down
204 virtual nsresult TransportFailed_s(TransportInfo &info);
205 // The transport is ready
206 virtual nsresult TransportReady_s(TransportInfo &info);
207 void UpdateRtcpMuxState(TransportInfo &info);
209 // Unhooks from signals
210 void DisconnectTransport_s(TransportInfo &info);
211 nsresult ConnectTransport_s(TransportInfo &info);
213 TransportInfo* GetTransportInfo_s(TransportFlow *flow);
215 void increment_rtp_packets_sent(int bytes);
216 void increment_rtcp_packets_sent();
217 void increment_rtp_packets_received(int bytes);
218 void increment_rtcp_packets_received();
220 virtual nsresult SendPacket(TransportFlow *flow, const void *data, int len);
222 // Process slots on transports
223 void StateChange(TransportFlow *flow, TransportLayer::State);
224 void RtpPacketReceived(TransportLayer *layer, const unsigned char *data,
225 size_t len);
226 void RtcpPacketReceived(TransportLayer *layer, const unsigned char *data,
227 size_t len);
228 void PacketReceived(TransportLayer *layer, const unsigned char *data,
229 size_t len);
231 Direction direction_;
232 RefPtr<MediaStream> stream_; // A pointer to the stream we are servicing.
233 // Written on the main thread.
234 // Used on STS and MediaStreamGraph threads.
235 TrackID track_id_; // The track on the stream.
236 // Written and used as the stream_;
237 int level_; // The m-line index (starting at 1, to match convention)
238 RefPtr<MediaSessionConduit> conduit_; // Our conduit. Written on the main
239 // thread. Read on STS thread.
241 // The transport objects. Read/written on STS thread.
242 TransportInfo rtp_;
243 TransportInfo rtcp_;
244 // These are for bundle. We have a separate set because when we have offered
245 // bundle, we do not know whether we will receive traffic on the transport
246 // in this pipeline's m-line, or the transport in the "master" m-line for
247 // the bundle. We need to be ready for either. Once this ambiguity is
248 // resolved, the transport we know that we'll be using will be set in
249 // rtp_transport_ and rtcp_transport_, and these will be unset.
250 // TODO(bcampen@mozilla.com): I'm pretty sure this could be leveraged for
251 // re-offer with a new address on an m-line too, with a little work.
252 nsAutoPtr<TransportInfo> possible_bundle_rtp_;
253 nsAutoPtr<TransportInfo> possible_bundle_rtcp_;
255 // Pointers to the threads we need. Initialized at creation
256 // and used all over the place.
257 nsCOMPtr<nsIEventTarget> main_thread_;
258 nsCOMPtr<nsIEventTarget> sts_thread_;
260 // Created on Init. Referenced by the conduit and eventually
261 // destroyed on the STS thread.
262 RefPtr<PipelineTransport> transport_;
264 // Only safe to access from STS thread.
265 // Build into TransportInfo?
266 int32_t rtp_packets_sent_;
267 int32_t rtcp_packets_sent_;
268 int32_t rtp_packets_received_;
269 int32_t rtcp_packets_received_;
270 int64_t rtp_bytes_sent_;
271 int64_t rtp_bytes_received_;
273 // Written on Init. Read on STS thread.
274 std::string pc_;
275 std::string description_;
277 // Written on Init, all following accesses are on the STS thread.
278 nsAutoPtr<MediaPipelineFilter> filter_;
279 nsAutoPtr<webrtc::RtpHeaderParser> rtp_parser_;
281 private:
282 nsresult Init_s();
284 bool IsRtp(const unsigned char *data, size_t len);
285 };
287 class GenericReceiveListener : public MediaStreamListener
288 {
289 public:
290 GenericReceiveListener(SourceMediaStream *source, TrackID track_id,
291 TrackRate track_rate)
292 : source_(source),
293 track_id_(track_id),
294 track_rate_(track_rate),
295 played_ticks_(0) {}
297 virtual ~GenericReceiveListener() {}
299 void AddSelf(MediaSegment* segment);
301 void SetPlayedTicks(TrackTicks time) {
302 played_ticks_ = time;
303 }
305 void EndTrack() {
306 source_->EndTrack(track_id_);
307 }
309 protected:
310 SourceMediaStream *source_;
311 TrackID track_id_;
312 TrackRate track_rate_;
313 TrackTicks played_ticks_;
314 };
316 class TrackAddedCallback {
317 public:
318 virtual void TrackAdded(TrackTicks current_ticks) = 0;
320 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(TrackAddedCallback);
322 protected:
323 virtual ~TrackAddedCallback() {}
324 };
326 class GenericReceiveListener;
328 class GenericReceiveCallback : public TrackAddedCallback
329 {
330 public:
331 GenericReceiveCallback(GenericReceiveListener* listener)
332 : listener_(listener) {}
334 void TrackAdded(TrackTicks time) {
335 listener_->SetPlayedTicks(time);
336 }
338 private:
339 RefPtr<GenericReceiveListener> listener_;
340 };
342 class ConduitDeleteEvent: public nsRunnable
343 {
344 public:
345 ConduitDeleteEvent(TemporaryRef<MediaSessionConduit> aConduit) :
346 mConduit(aConduit) {}
348 /* we exist solely to proxy release of the conduit */
349 NS_IMETHOD Run() { return NS_OK; }
350 private:
351 RefPtr<MediaSessionConduit> mConduit;
352 };
354 // A specialization of pipeline for reading from an input device
355 // and transmitting to the network.
356 class MediaPipelineTransmit : public MediaPipeline {
357 public:
358 // Set rtcp_transport to nullptr to use rtcp-mux
359 MediaPipelineTransmit(const std::string& pc,
360 nsCOMPtr<nsIEventTarget> main_thread,
361 nsCOMPtr<nsIEventTarget> sts_thread,
362 DOMMediaStream *domstream,
363 TrackID track_id,
364 int level,
365 RefPtr<MediaSessionConduit> conduit,
366 RefPtr<TransportFlow> rtp_transport,
367 RefPtr<TransportFlow> rtcp_transport) :
368 MediaPipeline(pc, TRANSMIT, main_thread, sts_thread,
369 domstream->GetStream(), track_id, level,
370 conduit, rtp_transport, rtcp_transport),
371 listener_(new PipelineListener(conduit)),
372 domstream_(domstream)
373 {}
375 // Initialize (stuff here may fail)
376 virtual nsresult Init();
378 // Called on the main thread.
379 virtual void DetachMediaStream() {
380 ASSERT_ON_THREAD(main_thread_);
381 domstream_->RemoveDirectListener(listener_);
382 domstream_ = nullptr;
383 stream_->RemoveListener(listener_);
384 // Let the listener be destroyed with the pipeline (or later).
385 stream_ = nullptr;
386 }
388 // Override MediaPipeline::TransportReady.
389 virtual nsresult TransportReady_s(TransportInfo &info);
391 // Separate class to allow ref counting
392 class PipelineListener : public MediaStreamDirectListener {
393 friend class MediaPipelineTransmit;
394 public:
395 PipelineListener(const RefPtr<MediaSessionConduit>& conduit)
396 : conduit_(conduit),
397 active_(false),
398 direct_connect_(false),
399 samples_10ms_buffer_(nullptr),
400 buffer_current_(0),
401 samplenum_10ms_(0)
402 #ifdef MOZILLA_INTERNAL_API
403 , last_img_(-1)
404 #endif // MOZILLA_INTERNAL_API
405 {
406 }
408 ~PipelineListener()
409 {
410 // release conduit on mainthread. Must use forget()!
411 nsresult rv = NS_DispatchToMainThread(new
412 ConduitDeleteEvent(conduit_.forget()), NS_DISPATCH_NORMAL);
413 MOZ_ASSERT(!NS_FAILED(rv),"Could not dispatch conduit shutdown to main");
414 if (NS_FAILED(rv)) {
415 MOZ_CRASH();
416 }
417 }
420 // XXX. This is not thread-safe but the hazard is just
421 // that active_ = true takes a while to propagate. Revisit
422 // when 823600 lands.
423 void SetActive(bool active) { active_ = active; }
425 // Implement MediaStreamListener
426 virtual void NotifyQueuedTrackChanges(MediaStreamGraph* graph, TrackID tid,
427 TrackRate rate,
428 TrackTicks offset,
429 uint32_t events,
430 const MediaSegment& queued_media) MOZ_OVERRIDE;
431 virtual void NotifyPull(MediaStreamGraph* aGraph, StreamTime aDesiredTime) MOZ_OVERRIDE {}
433 // Implement MediaStreamDirectListener
434 virtual void NotifyRealtimeData(MediaStreamGraph* graph, TrackID tid,
435 TrackRate rate,
436 TrackTicks offset,
437 uint32_t events,
438 const MediaSegment& media) MOZ_OVERRIDE;
440 private:
441 void NewData(MediaStreamGraph* graph, TrackID tid,
442 TrackRate rate,
443 TrackTicks offset,
444 uint32_t events,
445 const MediaSegment& media);
447 virtual void ProcessAudioChunk(AudioSessionConduit *conduit,
448 TrackRate rate, AudioChunk& chunk);
449 #ifdef MOZILLA_INTERNAL_API
450 virtual void ProcessVideoChunk(VideoSessionConduit *conduit,
451 TrackRate rate, VideoChunk& chunk);
452 #endif
453 RefPtr<MediaSessionConduit> conduit_;
454 volatile bool active_;
455 bool direct_connect_;
457 // These vars handle breaking audio samples into exact 10ms chunks:
458 // The buffer of 10ms audio samples that we will send once full
459 // (can be carried over from one call to another).
460 nsAutoArrayPtr<int16_t> samples_10ms_buffer_;
461 // The location of the pointer within that buffer (in units of samples).
462 int64_t buffer_current_;
463 // The number of samples in a 10ms audio chunk.
464 int64_t samplenum_10ms_;
466 #ifdef MOZILLA_INTERNAL_API
467 int32_t last_img_; // serial number of last Image
468 #endif // MOZILLA_INTERNAL_API
469 };
471 private:
472 RefPtr<PipelineListener> listener_;
473 DOMMediaStream *domstream_;
474 };
477 // A specialization of pipeline for reading from the network and
478 // rendering video.
479 class MediaPipelineReceive : public MediaPipeline {
480 public:
481 // Set rtcp_transport to nullptr to use rtcp-mux
482 MediaPipelineReceive(const std::string& pc,
483 nsCOMPtr<nsIEventTarget> main_thread,
484 nsCOMPtr<nsIEventTarget> sts_thread,
485 MediaStream *stream,
486 TrackID track_id,
487 int level,
488 RefPtr<MediaSessionConduit> conduit,
489 RefPtr<TransportFlow> rtp_transport,
490 RefPtr<TransportFlow> rtcp_transport,
491 RefPtr<TransportFlow> bundle_rtp_transport,
492 RefPtr<TransportFlow> bundle_rtcp_transport,
493 nsAutoPtr<MediaPipelineFilter> filter) :
494 MediaPipeline(pc, RECEIVE, main_thread, sts_thread,
495 stream, track_id, level, conduit, rtp_transport,
496 rtcp_transport),
497 segments_added_(0) {
498 filter_ = filter;
499 rtp_parser_ = webrtc::RtpHeaderParser::Create();
500 if (bundle_rtp_transport) {
501 if (bundle_rtcp_transport) {
502 MOZ_ASSERT(bundle_rtp_transport != bundle_rtcp_transport);
503 possible_bundle_rtp_ = new TransportInfo(bundle_rtp_transport, RTP);
504 possible_bundle_rtcp_ = new TransportInfo(bundle_rtcp_transport, RTCP);
505 } else {
506 possible_bundle_rtp_ = new TransportInfo(bundle_rtp_transport, MUX);
507 possible_bundle_rtcp_ = new TransportInfo(bundle_rtp_transport, MUX);
508 }
509 }
510 }
512 int segments_added() const { return segments_added_; }
514 protected:
515 int segments_added_;
517 private:
518 };
521 // A specialization of pipeline for reading from the network and
522 // rendering audio.
523 class MediaPipelineReceiveAudio : public MediaPipelineReceive {
524 public:
525 MediaPipelineReceiveAudio(const std::string& pc,
526 nsCOMPtr<nsIEventTarget> main_thread,
527 nsCOMPtr<nsIEventTarget> sts_thread,
528 MediaStream *stream,
529 TrackID track_id,
530 int level,
531 RefPtr<AudioSessionConduit> conduit,
532 RefPtr<TransportFlow> rtp_transport,
533 RefPtr<TransportFlow> rtcp_transport,
534 RefPtr<TransportFlow> bundle_rtp_transport,
535 RefPtr<TransportFlow> bundle_rtcp_transport,
536 nsAutoPtr<MediaPipelineFilter> filter) :
537 MediaPipelineReceive(pc, main_thread, sts_thread,
538 stream, track_id, level, conduit, rtp_transport,
539 rtcp_transport, bundle_rtp_transport,
540 bundle_rtcp_transport, filter),
541 listener_(new PipelineListener(stream->AsSourceStream(),
542 track_id, conduit)) {
543 }
545 virtual void DetachMediaStream() {
546 ASSERT_ON_THREAD(main_thread_);
547 listener_->EndTrack();
548 stream_->RemoveListener(listener_);
549 stream_ = nullptr;
550 }
552 virtual nsresult Init();
554 private:
555 // Separate class to allow ref counting
556 class PipelineListener : public GenericReceiveListener {
557 public:
558 PipelineListener(SourceMediaStream * source, TrackID track_id,
559 const RefPtr<MediaSessionConduit>& conduit);
561 ~PipelineListener()
562 {
563 // release conduit on mainthread. Must use forget()!
564 nsresult rv = NS_DispatchToMainThread(new
565 ConduitDeleteEvent(conduit_.forget()), NS_DISPATCH_NORMAL);
566 MOZ_ASSERT(!NS_FAILED(rv),"Could not dispatch conduit shutdown to main");
567 if (NS_FAILED(rv)) {
568 MOZ_CRASH();
569 }
570 }
572 // Implement MediaStreamListener
573 virtual void NotifyQueuedTrackChanges(MediaStreamGraph* graph, TrackID tid,
574 TrackRate rate,
575 TrackTicks offset,
576 uint32_t events,
577 const MediaSegment& queued_media) MOZ_OVERRIDE {}
578 virtual void NotifyPull(MediaStreamGraph* graph, StreamTime desired_time) MOZ_OVERRIDE;
580 private:
581 RefPtr<MediaSessionConduit> conduit_;
582 };
584 RefPtr<PipelineListener> listener_;
585 };
588 // A specialization of pipeline for reading from the network and
589 // rendering video.
590 class MediaPipelineReceiveVideo : public MediaPipelineReceive {
591 public:
592 MediaPipelineReceiveVideo(const std::string& pc,
593 nsCOMPtr<nsIEventTarget> main_thread,
594 nsCOMPtr<nsIEventTarget> sts_thread,
595 MediaStream *stream,
596 TrackID track_id,
597 int level,
598 RefPtr<VideoSessionConduit> conduit,
599 RefPtr<TransportFlow> rtp_transport,
600 RefPtr<TransportFlow> rtcp_transport,
601 RefPtr<TransportFlow> bundle_rtp_transport,
602 RefPtr<TransportFlow> bundle_rtcp_transport,
603 nsAutoPtr<MediaPipelineFilter> filter) :
604 MediaPipelineReceive(pc, main_thread, sts_thread,
605 stream, track_id, level, conduit, rtp_transport,
606 rtcp_transport, bundle_rtp_transport,
607 bundle_rtcp_transport, filter),
608 renderer_(new PipelineRenderer(MOZ_THIS_IN_INITIALIZER_LIST())),
609 listener_(new PipelineListener(stream->AsSourceStream(), track_id)) {
610 }
612 // Called on the main thread.
613 virtual void DetachMediaStream() {
614 ASSERT_ON_THREAD(main_thread_);
616 listener_->EndTrack();
617 // stop generating video and thus stop invoking the PipelineRenderer
618 // and PipelineListener - the renderer has a raw ptr to the Pipeline to
619 // avoid cycles, and the render callbacks are invoked from a different
620 // thread so simple null-checks would cause TSAN bugs without locks.
621 static_cast<VideoSessionConduit*>(conduit_.get())->DetachRenderer();
622 stream_->RemoveListener(listener_);
623 stream_ = nullptr;
624 }
626 virtual nsresult Init();
628 private:
629 class PipelineRenderer : public VideoRenderer {
630 public:
631 PipelineRenderer(MediaPipelineReceiveVideo *pipeline) :
632 pipeline_(pipeline) {}
634 void Detach() { pipeline_ = nullptr; }
636 // Implement VideoRenderer
637 virtual void FrameSizeChange(unsigned int width,
638 unsigned int height,
639 unsigned int number_of_streams) {
640 pipeline_->listener_->FrameSizeChange(width, height, number_of_streams);
641 }
643 virtual void RenderVideoFrame(const unsigned char* buffer,
644 unsigned int buffer_size,
645 uint32_t time_stamp,
646 int64_t render_time,
647 const ImageHandle& handle) {
648 pipeline_->listener_->RenderVideoFrame(buffer, buffer_size, time_stamp,
649 render_time,
650 handle.GetImage());
651 }
653 private:
654 MediaPipelineReceiveVideo *pipeline_; // Raw pointer to avoid cycles
655 };
657 // Separate class to allow ref counting
658 class PipelineListener : public GenericReceiveListener {
659 public:
660 PipelineListener(SourceMediaStream * source, TrackID track_id);
662 // Implement MediaStreamListener
663 virtual void NotifyQueuedTrackChanges(MediaStreamGraph* graph, TrackID tid,
664 TrackRate rate,
665 TrackTicks offset,
666 uint32_t events,
667 const MediaSegment& queued_media) MOZ_OVERRIDE {}
668 virtual void NotifyPull(MediaStreamGraph* graph, StreamTime desired_time) MOZ_OVERRIDE;
670 // Accessors for external writes from the renderer
671 void FrameSizeChange(unsigned int width,
672 unsigned int height,
673 unsigned int number_of_streams) {
674 ReentrantMonitorAutoEnter enter(monitor_);
676 width_ = width;
677 height_ = height;
678 }
680 void RenderVideoFrame(const unsigned char* buffer,
681 unsigned int buffer_size,
682 uint32_t time_stamp,
683 int64_t render_time,
684 const RefPtr<layers::Image>& video_image);
686 private:
687 int width_;
688 int height_;
689 #ifdef MOZILLA_INTERNAL_API
690 nsRefPtr<layers::ImageContainer> image_container_;
691 nsRefPtr<layers::Image> image_;
692 #endif
693 mozilla::ReentrantMonitor monitor_; // Monitor for processing WebRTC frames.
694 // Protects image_ against:
695 // - Writing from the GIPS thread
696 // - Reading from the MSG thread
697 };
699 friend class PipelineRenderer;
701 RefPtr<PipelineRenderer> renderer_;
702 RefPtr<PipelineListener> listener_;
703 };
706 } // end namespace
707 #endif