Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / libjingle / source / talk / media / base / filemediaengine.cc
1 // libjingle
2 // Copyright 2004 Google Inc.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are met:
6 //
7 //  1. Redistributions of source code must retain the above copyright notice,
8 //     this list of conditions and the following disclaimer.
9 //  2. Redistributions in binary form must reproduce the above copyright notice,
10 //     this list of conditions and the following disclaimer in the documentation
11 //     and/or other materials provided with the distribution.
12 //  3. The name of the author may not be used to endorse or promote products
13 //     derived from this software without specific prior written permission.
14 //
15 // THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
16 // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
17 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
18 // EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
19 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
21 // OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22 // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23 // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
24 // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
26 #include "talk/media/base/filemediaengine.h"
27
28 #include <limits.h>
29
30 #include "talk/media/base/rtpdump.h"
31 #include "talk/media/base/rtputils.h"
32 #include "talk/media/base/streamparams.h"
33 #include "webrtc/base/buffer.h"
34 #include "webrtc/base/event.h"
35 #include "webrtc/base/logging.h"
36 #include "webrtc/base/pathutils.h"
37 #include "webrtc/base/stream.h"
38
39 namespace cricket {
40
41 ///////////////////////////////////////////////////////////////////////////
42 // Implementation of FileMediaEngine.
43 ///////////////////////////////////////////////////////////////////////////
44 int FileMediaEngine::GetCapabilities() {
45   int capabilities = 0;
46   if (!voice_input_filename_.empty()) {
47     capabilities |= AUDIO_SEND;
48   }
49   if (!voice_output_filename_.empty()) {
50     capabilities |= AUDIO_RECV;
51   }
52   if (!video_input_filename_.empty()) {
53     capabilities |= VIDEO_SEND;
54   }
55   if (!video_output_filename_.empty()) {
56     capabilities |= VIDEO_RECV;
57   }
58   return capabilities;
59 }
60
61 VoiceMediaChannel* FileMediaEngine::CreateChannel() {
62   rtc::FileStream* input_file_stream = NULL;
63   rtc::FileStream* output_file_stream = NULL;
64
65   if (voice_input_filename_.empty() && voice_output_filename_.empty())
66     return NULL;
67   if (!voice_input_filename_.empty()) {
68     input_file_stream = rtc::Filesystem::OpenFile(
69         rtc::Pathname(voice_input_filename_), "rb");
70     if (!input_file_stream) {
71       LOG(LS_ERROR) << "Not able to open the input audio stream file.";
72       return NULL;
73     }
74   }
75
76   if (!voice_output_filename_.empty()) {
77     output_file_stream = rtc::Filesystem::OpenFile(
78         rtc::Pathname(voice_output_filename_), "wb");
79     if (!output_file_stream) {
80       delete input_file_stream;
81       LOG(LS_ERROR) << "Not able to open the output audio stream file.";
82       return NULL;
83     }
84   }
85
86   return new FileVoiceChannel(input_file_stream, output_file_stream,
87                               rtp_sender_thread_);
88 }
89
90 VideoMediaChannel* FileMediaEngine::CreateVideoChannel(
91     const VideoOptions& options,
92     VoiceMediaChannel* voice_ch) {
93   rtc::FileStream* input_file_stream = NULL;
94   rtc::FileStream* output_file_stream = NULL;
95
96   if (video_input_filename_.empty() && video_output_filename_.empty())
97       return NULL;
98
99   if (!video_input_filename_.empty()) {
100     input_file_stream = rtc::Filesystem::OpenFile(
101         rtc::Pathname(video_input_filename_), "rb");
102     if (!input_file_stream) {
103       LOG(LS_ERROR) << "Not able to open the input video stream file.";
104       return NULL;
105     }
106   }
107
108   if (!video_output_filename_.empty()) {
109     output_file_stream = rtc::Filesystem::OpenFile(
110         rtc::Pathname(video_output_filename_), "wb");
111     if (!output_file_stream) {
112       delete input_file_stream;
113       LOG(LS_ERROR) << "Not able to open the output video stream file.";
114       return NULL;
115     }
116   }
117
118   FileVideoChannel* channel = new FileVideoChannel(
119       input_file_stream, output_file_stream, rtp_sender_thread_);
120   channel->SetOptions(options);
121   return channel;
122 }
123
124 ///////////////////////////////////////////////////////////////////////////
125 // Definition of RtpSenderReceiver.
126 ///////////////////////////////////////////////////////////////////////////
127 class RtpSenderReceiver : public rtc::MessageHandler {
128  public:
129   RtpSenderReceiver(MediaChannel* channel,
130                     rtc::StreamInterface* input_file_stream,
131                     rtc::StreamInterface* output_file_stream,
132                     rtc::Thread* sender_thread);
133   virtual ~RtpSenderReceiver();
134
135   // Called by media channel. Context: media channel thread.
136   bool SetSend(bool send);
137   void SetSendSsrc(uint32 ssrc);
138   void OnPacketReceived(rtc::Buffer* packet);
139
140   // Override virtual method of parent MessageHandler. Context: Worker Thread.
141   virtual void OnMessage(rtc::Message* pmsg);
142
143  private:
144   // Read the next RTP dump packet, whose RTP SSRC is the same as first_ssrc_.
145   // Return true if successful.
146   bool ReadNextPacket(RtpDumpPacket* packet);
147   // Send a RTP packet to the network. The input parameter data points to the
148   // start of the RTP packet and len is the packet size. Return true if the sent
149   // size is equal to len.
150   bool SendRtpPacket(const void* data, size_t len);
151
152   MediaChannel* media_channel_;
153   rtc::scoped_ptr<rtc::StreamInterface> input_stream_;
154   rtc::scoped_ptr<rtc::StreamInterface> output_stream_;
155   rtc::scoped_ptr<RtpDumpLoopReader> rtp_dump_reader_;
156   rtc::scoped_ptr<RtpDumpWriter> rtp_dump_writer_;
157   rtc::Thread* sender_thread_;
158   bool own_sender_thread_;
159   // RTP dump packet read from the input stream.
160   RtpDumpPacket rtp_dump_packet_;
161   uint32 start_send_time_;
162   bool sending_;
163   bool first_packet_;
164   uint32 first_ssrc_;
165
166   DISALLOW_COPY_AND_ASSIGN(RtpSenderReceiver);
167 };
168
169 ///////////////////////////////////////////////////////////////////////////
170 // Implementation of RtpSenderReceiver.
171 ///////////////////////////////////////////////////////////////////////////
172 RtpSenderReceiver::RtpSenderReceiver(
173     MediaChannel* channel,
174     rtc::StreamInterface* input_file_stream,
175     rtc::StreamInterface* output_file_stream,
176     rtc::Thread* sender_thread)
177     : media_channel_(channel),
178       input_stream_(input_file_stream),
179       output_stream_(output_file_stream),
180       sending_(false),
181       first_packet_(true) {
182   if (sender_thread == NULL) {
183     sender_thread_ = new rtc::Thread();
184     own_sender_thread_ = true;
185   } else {
186     sender_thread_ = sender_thread;
187     own_sender_thread_ = false;
188   }
189
190   if (input_stream_) {
191     rtp_dump_reader_.reset(new RtpDumpLoopReader(input_stream_.get()));
192     // Start the sender thread, which reads rtp dump records, waits based on
193     // the record timestamps, and sends the RTP packets to the network.
194     if (own_sender_thread_) {
195       sender_thread_->Start();
196     }
197   }
198
199   // Create a rtp dump writer for the output RTP dump stream.
200   if (output_stream_) {
201     rtp_dump_writer_.reset(new RtpDumpWriter(output_stream_.get()));
202   }
203 }
204
205 RtpSenderReceiver::~RtpSenderReceiver() {
206   if (own_sender_thread_) {
207     sender_thread_->Stop();
208     delete sender_thread_;
209   }
210 }
211
212 bool RtpSenderReceiver::SetSend(bool send) {
213   bool was_sending = sending_;
214   sending_ = send;
215   if (!was_sending && sending_) {
216     sender_thread_->PostDelayed(0, this);  // Wake up the send thread.
217     start_send_time_ = rtc::Time();
218   }
219   return true;
220 }
221
222 void RtpSenderReceiver::SetSendSsrc(uint32 ssrc) {
223   if (rtp_dump_reader_) {
224     rtp_dump_reader_->SetSsrc(ssrc);
225   }
226 }
227
228 void RtpSenderReceiver::OnPacketReceived(rtc::Buffer* packet) {
229   if (rtp_dump_writer_) {
230     rtp_dump_writer_->WriteRtpPacket(packet->data(), packet->length());
231   }
232 }
233
234 void RtpSenderReceiver::OnMessage(rtc::Message* pmsg) {
235   if (!sending_) {
236     // If the sender thread is not sending, ignore this message. The thread goes
237     // to sleep until SetSend(true) wakes it up.
238     return;
239   }
240   if (!first_packet_) {
241     // Send the previously read packet.
242     SendRtpPacket(&rtp_dump_packet_.data[0], rtp_dump_packet_.data.size());
243   }
244
245   if (ReadNextPacket(&rtp_dump_packet_)) {
246     int wait = rtc::TimeUntil(
247         start_send_time_ + rtp_dump_packet_.elapsed_time);
248     wait = rtc::_max(0, wait);
249     sender_thread_->PostDelayed(wait, this);
250   } else {
251     sender_thread_->Quit();
252   }
253 }
254
255 bool RtpSenderReceiver::ReadNextPacket(RtpDumpPacket* packet) {
256   while (rtc::SR_SUCCESS == rtp_dump_reader_->ReadPacket(packet)) {
257     uint32 ssrc;
258     if (!packet->GetRtpSsrc(&ssrc)) {
259       return false;
260     }
261     if (first_packet_) {
262       first_packet_ = false;
263       first_ssrc_ = ssrc;
264     }
265     if (ssrc == first_ssrc_) {
266       return true;
267     }
268   }
269   return false;
270 }
271
272 bool RtpSenderReceiver::SendRtpPacket(const void* data, size_t len) {
273   if (!media_channel_)
274     return false;
275
276   rtc::Buffer packet(data, len, kMaxRtpPacketLen);
277   return media_channel_->SendPacket(&packet);
278 }
279
280 ///////////////////////////////////////////////////////////////////////////
281 // Implementation of FileVoiceChannel.
282 ///////////////////////////////////////////////////////////////////////////
283 FileVoiceChannel::FileVoiceChannel(
284     rtc::StreamInterface* input_file_stream,
285     rtc::StreamInterface* output_file_stream,
286     rtc::Thread* rtp_sender_thread)
287     : send_ssrc_(0),
288       rtp_sender_receiver_(new RtpSenderReceiver(this, input_file_stream,
289                                                  output_file_stream,
290                                                  rtp_sender_thread)) {}
291
292 FileVoiceChannel::~FileVoiceChannel() {}
293
294 bool FileVoiceChannel::SetSendCodecs(const std::vector<AudioCodec>& codecs) {
295   // TODO(whyuan): Check the format of RTP dump input.
296   return true;
297 }
298
299 bool FileVoiceChannel::SetSend(SendFlags flag) {
300   return rtp_sender_receiver_->SetSend(flag != SEND_NOTHING);
301 }
302
303 bool FileVoiceChannel::AddSendStream(const StreamParams& sp) {
304   if (send_ssrc_ != 0 || sp.ssrcs.size() != 1) {
305     LOG(LS_ERROR) << "FileVoiceChannel only supports one send stream.";
306     return false;
307   }
308   send_ssrc_ = sp.ssrcs[0];
309   rtp_sender_receiver_->SetSendSsrc(send_ssrc_);
310   return true;
311 }
312
313 bool FileVoiceChannel::RemoveSendStream(uint32 ssrc) {
314   if (ssrc != send_ssrc_)
315     return false;
316   send_ssrc_ = 0;
317   rtp_sender_receiver_->SetSendSsrc(send_ssrc_);
318   return true;
319 }
320
321 void FileVoiceChannel::OnPacketReceived(
322     rtc::Buffer* packet, const rtc::PacketTime& packet_time) {
323   rtp_sender_receiver_->OnPacketReceived(packet);
324 }
325
326 ///////////////////////////////////////////////////////////////////////////
327 // Implementation of FileVideoChannel.
328 ///////////////////////////////////////////////////////////////////////////
329 FileVideoChannel::FileVideoChannel(
330     rtc::StreamInterface* input_file_stream,
331     rtc::StreamInterface* output_file_stream,
332     rtc::Thread* rtp_sender_thread)
333     : send_ssrc_(0),
334       rtp_sender_receiver_(new RtpSenderReceiver(this, input_file_stream,
335                                                  output_file_stream,
336                                                  rtp_sender_thread)) {}
337
338 FileVideoChannel::~FileVideoChannel() {}
339
340 bool FileVideoChannel::SetSendCodecs(const std::vector<VideoCodec>& codecs) {
341   // TODO(whyuan): Check the format of RTP dump input.
342   return true;
343 }
344
345 bool FileVideoChannel::SetSend(bool send) {
346   return rtp_sender_receiver_->SetSend(send);
347 }
348
349 bool FileVideoChannel::AddSendStream(const StreamParams& sp) {
350   if (send_ssrc_ != 0 || sp.ssrcs.size() != 1) {
351     LOG(LS_ERROR) << "FileVideoChannel only support one send stream.";
352     return false;
353   }
354   send_ssrc_ = sp.ssrcs[0];
355   rtp_sender_receiver_->SetSendSsrc(send_ssrc_);
356   return true;
357 }
358
359 bool FileVideoChannel::RemoveSendStream(uint32 ssrc) {
360   if (ssrc != send_ssrc_)
361     return false;
362   send_ssrc_ = 0;
363   rtp_sender_receiver_->SetSendSsrc(send_ssrc_);
364   return true;
365 }
366
367 void FileVideoChannel::OnPacketReceived(
368     rtc::Buffer* packet, const rtc::PacketTime& packet_time) {
369   rtp_sender_receiver_->OnPacketReceived(packet);
370 }
371
372 }  // namespace cricket