]> git.sesse.net Git - casparcg/blob - modules/ffmpeg/producer/ffmpeg_producer.cpp
* Fixed compilation problems in Linux.
[casparcg] / modules / ffmpeg / producer / ffmpeg_producer.cpp
1 /*
2 * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>
3 *
4 * This file is part of CasparCG (www.casparcg.com).
5 *
6 * CasparCG is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * CasparCG is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with CasparCG. If not, see <http://www.gnu.org/licenses/>.
18 *
19 * Author: Robert Nagy, ronag89@gmail.com
20 */
21
22 #include "../StdAfx.h"
23
24 #include "ffmpeg_producer.h"
25
26 #include "../ffmpeg_error.h"
27
28 #include "muxer/frame_muxer.h"
29 #include "input/input.h"
30 #include "util/util.h"
31 #include "audio/audio_decoder.h"
32 #include "video/video_decoder.h"
33
34 #include <common/env.h>
35 #include <common/log.h>
36 #include <common/param.h>
37 #include <common/diagnostics/graph.h>
38 #include <common/future.h>
39 #include <common/timer.h>
40 #include <common/assert.h>
41
42 #include <core/video_format.h>
43 #include <core/producer/frame_producer.h>
44 #include <core/frame/audio_channel_layout.h>
45 #include <core/frame/frame_factory.h>
46 #include <core/frame/draw_frame.h>
47 #include <core/frame/frame_transform.h>
48 #include <core/monitor/monitor.h>
49 #include <core/help/help_repository.h>
50 #include <core/help/help_sink.h>
51
52 #include <boost/algorithm/string.hpp>
53 #include <boost/filesystem.hpp>
54 #include <boost/property_tree/ptree.hpp>
55 #include <boost/regex.hpp>
56 #include <boost/thread/future.hpp>
57
58 #include <tbb/parallel_invoke.h>
59
60 #include <limits>
61 #include <memory>
62 #include <queue>
63
64 namespace caspar { namespace ffmpeg {
65
66 std::wstring get_relative_or_original(
67                 const std::wstring& filename,
68                 const boost::filesystem::path& relative_to)
69 {
70         boost::filesystem::path file(filename);
71         auto result = file.filename().wstring();
72
73         boost::filesystem::path current_path = file;
74
75         while (true)
76         {
77                 current_path = current_path.parent_path();
78
79                 if (boost::filesystem::equivalent(current_path, relative_to))
80                         break;
81
82                 if (current_path.empty())
83                         return filename;
84
85                 result = current_path.filename().wstring() + L"/" + result;
86         }
87
88         return result;
89 }
90
91 struct ffmpeg_producer : public core::frame_producer_base
92 {
93         spl::shared_ptr<core::monitor::subject>                 monitor_subject_;
94         const std::wstring                                                              filename_;
95         const std::wstring                                                              path_relative_to_media_ = get_relative_or_original(filename_, env::media_folder());
96         
97         const spl::shared_ptr<diagnostics::graph>               graph_;
98                                         
99         const spl::shared_ptr<core::frame_factory>              frame_factory_;
100         const core::video_format_desc                                   format_desc_;
101
102         input                                                                                   input_; 
103
104         const double                                                                    fps_                                    = read_fps(input_.context(), format_desc_.fps);
105         const uint32_t                                                                  start_;
106                 
107         std::unique_ptr<video_decoder>                                  video_decoder_;
108         std::unique_ptr<audio_decoder>                                  audio_decoder_; 
109         std::unique_ptr<frame_muxer>                                    muxer_;
110         core::constraints                                                               constraints_;
111         
112         core::draw_frame                                                                last_frame_                             = core::draw_frame::empty();
113
114         boost::optional<uint32_t>                                               seek_target_;
115         
116 public:
117         explicit ffmpeg_producer(
118                         const spl::shared_ptr<core::frame_factory>& frame_factory, 
119                         const core::video_format_desc& format_desc,
120                         const std::wstring& channel_layout_spec,
121                         const std::wstring& filename,
122                         const std::wstring& filter,
123                         bool loop,
124                         uint32_t start,
125                         uint32_t length)
126                 : filename_(filename)
127                 , frame_factory_(frame_factory)         
128                 , format_desc_(format_desc)
129                 , input_(graph_, filename_, loop, start, length)
130                 , fps_(read_fps(input_.context(), format_desc_.fps))
131                 , start_(start)
132         {
133                 graph_->set_color("frame-time", diagnostics::color(0.1f, 1.0f, 0.1f));
134                 graph_->set_color("underflow", diagnostics::color(0.6f, 0.3f, 0.9f));   
135                 diagnostics::register_graph(graph_);
136                 
137
138                 try
139                 {
140                         video_decoder_.reset(new video_decoder(input_));
141                         video_decoder_->monitor_output().attach_parent(monitor_subject_);
142                         constraints_.width.set(video_decoder_->width());
143                         constraints_.height.set(video_decoder_->height());
144                         
145                         CASPAR_LOG(info) << print() << L" " << video_decoder_->print();
146                 }
147                 catch(averror_stream_not_found&)
148                 {
149                         //CASPAR_LOG(warning) << print() << " No video-stream found. Running without video.";   
150                 }
151                 catch(...)
152                 {
153                         CASPAR_LOG_CURRENT_EXCEPTION();
154                         CASPAR_LOG(warning) << print() << "Failed to open video-stream. Running without video.";        
155                 }
156
157                 auto channel_layout = core::audio_channel_layout::invalid();
158
159                 try
160                 {
161                         audio_decoder_ .reset(new audio_decoder(input_, format_desc_, channel_layout_spec));
162                         audio_decoder_->monitor_output().attach_parent(monitor_subject_);
163
164                         channel_layout = audio_decoder_->channel_layout();
165                         
166                         CASPAR_LOG(info) << print() << L" " << audio_decoder_->print();
167                 }
168                 catch(averror_stream_not_found&)
169                 {
170                         //CASPAR_LOG(warning) << print() << " No audio-stream found. Running without audio.";   
171                 }
172                 catch(...)
173                 {
174                         CASPAR_LOG_CURRENT_EXCEPTION();
175                         CASPAR_LOG(warning) << print() << " Failed to open audio-stream. Running without audio.";               
176                 }
177
178                 muxer_.reset(new frame_muxer(fps_, frame_factory, format_desc_, channel_layout, filter));
179                 
180                 decode_next_frame();
181
182                 CASPAR_LOG(info) << print() << L" Initialized";
183         }
184
185         // frame_producer
186         
187         core::draw_frame receive_impl() override
188         {                               
189                 auto frame = core::draw_frame::late();          
190                 
191                 caspar::timer frame_timer;
192                 
193                 end_seek();
194                                 
195                 decode_next_frame();
196                 
197                 if(!muxer_->empty())
198                 {
199                         last_frame_ = frame = std::move(muxer_->front());
200                         muxer_->pop();
201                 }
202                 else
203                         graph_->set_tag("underflow");
204                                                                         
205                 graph_->set_value("frame-time", frame_timer.elapsed()*format_desc_.fps*0.5);
206                 *monitor_subject_
207                                 << core::monitor::message("/profiler/time")     % frame_timer.elapsed() % (1.0/format_desc_.fps);                       
208                 *monitor_subject_
209                                 << core::monitor::message("/file/frame")        % static_cast<int32_t>(file_frame_number())
210                                                                                                                         % static_cast<int32_t>(file_nb_frames())
211                                 << core::monitor::message("/file/fps")          % fps_
212                                 << core::monitor::message("/file/path")         % path_relative_to_media_
213                                 << core::monitor::message("/loop")                      % input_.loop();
214                                                 
215                 return frame;
216         }
217
218         core::draw_frame last_frame() override
219         {
220                 end_seek();
221                 return core::draw_frame::still(last_frame_);
222         }
223
224         core::constraints& pixel_constraints() override
225         {
226                 return constraints_;
227         }
228
229         uint32_t nb_frames() const override
230         {
231                 if(input_.loop())
232                         return std::numeric_limits<uint32_t>::max();
233
234                 uint32_t nb_frames = file_nb_frames();
235
236                 nb_frames = std::min(input_.length(), nb_frames);
237                 nb_frames = muxer_->calc_nb_frames(nb_frames);
238                 
239                 return nb_frames > start_ ? nb_frames - start_ : 0;
240         }
241
242         uint32_t file_nb_frames() const
243         {
244                 uint32_t file_nb_frames = 0;
245                 file_nb_frames = std::max(file_nb_frames, video_decoder_ ? video_decoder_->nb_frames() : 0);
246                 file_nb_frames = std::max(file_nb_frames, audio_decoder_ ? audio_decoder_->nb_frames() : 0);
247                 return file_nb_frames;
248         }
249
250         uint32_t file_frame_number() const
251         {
252                 return video_decoder_ ? video_decoder_->file_frame_number() : 0;
253         }
254                 
255         std::future<std::wstring> call(const std::vector<std::wstring>& params) override
256         {
257                 static const boost::wregex loop_exp(LR"(LOOP\s*(?<VALUE>\d?)?)", boost::regex::icase);
258                 static const boost::wregex seek_exp(LR"(SEEK\s+(?<VALUE>\d+))", boost::regex::icase);
259                 static const boost::wregex length_exp(LR"(LENGTH\s+(?<VALUE>\d+)?)", boost::regex::icase);
260                 static const boost::wregex start_exp(LR"(START\\s+(?<VALUE>\\d+)?)", boost::regex::icase);
261
262                 auto param = boost::algorithm::join(params, L" ");
263                 
264                 std::wstring result;
265                         
266                 boost::wsmatch what;
267                 if(boost::regex_match(param, what, loop_exp))
268                 {
269                         auto value = what["VALUE"].str();
270                         if(!value.empty())
271                                 input_.loop(boost::lexical_cast<bool>(value));
272                         result = boost::lexical_cast<std::wstring>(loop());
273                 }
274                 else if(boost::regex_match(param, what, seek_exp))
275                 {
276                         auto value = what["VALUE"].str();
277                         seek(boost::lexical_cast<uint32_t>(value));
278                 }
279                 else if(boost::regex_match(param, what, length_exp))
280                 {
281                         auto value = what["VALUE"].str();
282                         if(!value.empty())
283                                 length(boost::lexical_cast<uint32_t>(value));                   
284                         result = boost::lexical_cast<std::wstring>(length());
285                 }
286                 else if(boost::regex_match(param, what, start_exp))
287                 {
288                         auto value = what["VALUE"].str();
289                         if(!value.empty())
290                                 start(boost::lexical_cast<uint32_t>(value));
291                         result = boost::lexical_cast<std::wstring>(start());
292                 }
293                 else
294                         CASPAR_THROW_EXCEPTION(invalid_argument());
295
296                 return make_ready_future(std::move(result));
297         }
298                                 
299         std::wstring print() const override
300         {
301                 return L"ffmpeg[" + boost::filesystem::path(filename_).filename().wstring() + L"|" 
302                                                   + print_mode() + L"|" 
303                                                   + boost::lexical_cast<std::wstring>(file_frame_number()) + L"/" + boost::lexical_cast<std::wstring>(file_nb_frames()) + L"]";
304         }
305
306         std::wstring name() const override
307         {
308                 return L"ffmpeg";
309         }
310
311         boost::property_tree::wptree info() const override
312         {
313                 boost::property_tree::wptree info;
314                 info.add(L"type",                               L"ffmpeg");
315                 info.add(L"filename",                   filename_);
316                 info.add(L"width",                              video_decoder_ ? video_decoder_->width() : 0);
317                 info.add(L"height",                             video_decoder_ ? video_decoder_->height() : 0);
318                 info.add(L"progressive",                video_decoder_ ? video_decoder_->is_progressive() : 0);
319                 info.add(L"fps",                                fps_);
320                 info.add(L"loop",                               input_.loop());
321                 info.add(L"frame-number",               frame_number());
322                 auto nb_frames2 = nb_frames();
323                 info.add(L"nb-frames",                  nb_frames2 == std::numeric_limits<int64_t>::max() ? -1 : nb_frames2);
324                 info.add(L"file-frame-number",  file_frame_number());
325                 info.add(L"file-nb-frames",             file_nb_frames());
326                 return info;
327         }
328         
329         core::monitor::subject& monitor_output()
330         {
331                 return *monitor_subject_;
332         }
333
334         // ffmpeg_producer
335         
336         void end_seek()
337         {
338                 for(int n = 0; n < 8 && (last_frame_ == core::draw_frame::empty() || (seek_target_ && file_frame_number() != *seek_target_+2)); ++n)
339                 {
340                         decode_next_frame();
341                         if(!muxer_->empty())
342                         {
343                                 last_frame_ = muxer_->front();
344                                 seek_target_.reset();
345                         }
346                 }
347         }
348
349         void loop(bool value)
350         {
351                 input_.loop(value);
352         }
353
354         bool loop() const
355         {
356                 return input_.loop();
357         }
358
359         void length(uint32_t value)
360         {
361                 input_.length(value);
362         }
363
364         uint32_t length()
365         {
366                 return input_.length();
367         }
368         
369         void start(uint32_t value)
370         {
371                 input_.start(value);
372         }
373
374         uint32_t start()
375         {
376                 return input_.start();
377         }
378
379         void seek(uint32_t target)
380         {               
381                 seek_target_ = std::min(target, file_nb_frames());
382
383                 input_.seek(*seek_target_);
384                 muxer_->clear();
385         }
386
387         std::wstring print_mode() const
388         {
389                 return ffmpeg::print_mode(video_decoder_ ? video_decoder_->width() : 0, 
390                         video_decoder_ ? video_decoder_->height() : 0, 
391                         fps_, 
392                         video_decoder_ ? !video_decoder_->is_progressive() : false);
393         }
394                         
395         void decode_next_frame()
396         {
397                 for(int n = 0; n < 32 && muxer_->empty(); ++n)
398                 {
399                         if(!muxer_->video_ready())
400                                 muxer_->push_video(video_decoder_ ? (*video_decoder_)() : create_frame());
401                         if(!muxer_->audio_ready())
402                                 muxer_->push_audio(audio_decoder_ ? (*audio_decoder_)() : create_frame());
403                 }
404
405                 graph_->set_text(print());
406         }
407 };
408
409 void describe_producer(core::help_sink& sink, const core::help_repository& repo)
410 {
411         sink.short_description(L"A producer for playing media files supported by FFmpeg.");
412         sink.syntax(L"[clip:string] {[loop:LOOP]} {START,SEEK [start:int]} {LENGTH [start:int]} {FILTER [filter:string]} {CHANNEL_LAYOUT [channel_layout:string]}");
413         sink.para()
414                 ->text(L"The FFmpeg Producer can play all media that FFmpeg can play, which includes many ")
415                 ->text(L"QuickTime video codec such as Animation, PNG, PhotoJPEG, MotionJPEG, as well as ")
416                 ->text(L"H.264, FLV, WMV and several audio codecs as well as uncompressed audio.");
417         sink.definitions()
418                 ->item(L"clip", L"The file without the file extension to play. It should reside under the media folder.")
419                 ->item(L"loop", L"Will cause the media file to loop between start and start + length")
420                 ->item(L"start", L"Optionally sets the start frame. 0 by default. If loop is specified this will be the frame where it starts over again.")
421                 ->item(L"length", L"Optionally sets the length of the clip. If not specified the clip will be played to the end. If loop is specified the file will jump to start position once this number of frames has been played.")
422                 ->item(L"filter", L"If specified, will be used as an FFmpeg video filter.")
423                 ->item(L"channel_layout",
424                                 L"Optionally override the automatically deduced audio channel layout. "
425                                 L"Either a named layout as specified in casparcg.config or in the format [type:string]:[channel_order:string] for a custom layout.");
426         sink.para()->text(L"Examples:");
427         sink.example(L">> PLAY 1-10 folder/clip", L"to play all frames in a clip and stop at the last frame.");
428         sink.example(L">> PLAY 1-10 folder/clip LOOP", L"to loop a clip between the first frame and the last frame.");
429         sink.example(L">> PLAY 1-10 folder/clip LOOP START 10", L"to loop a clip between frame 10 and the last frame.");
430         sink.example(L">> PLAY 1-10 folder/clip LOOP START 10 LENGTH 50", L"to loop a clip between frame 10 and frame 60.");
431         sink.example(L">> PLAY 1-10 folder/clip START 10 LENGTH 50", L"to play frames 10-60 in a clip and stop.");
432         sink.example(L">> PLAY 1-10 folder/clip FILTER yadif=1,-1", L"to deinterlace the video.");
433         sink.example(L">> PLAY 1-10 folder/clip CHANNEL_LAYOUT film", L"given the defaults in casparcg.config this will specifies that the clip has 6 audio channels of the type 5.1 and that they are in the order FL FC FR BL BR LFE regardless of what ffmpeg says.");
434         sink.example(L">> PLAY 1-10 folder/clip CHANNEL_LAYOUT \"5.1:LFE FL FC FR BL BR\"", L"specifies that the clip has 6 audio channels of the type 5.1 and that they are in the specified order regardless of what ffmpeg says.");
435         sink.para()->text(L"The FFmpeg producer also supports changing some of the settings via CALL:");
436         sink.example(L">> CALL 1-10 LOOP 1");
437         sink.example(L">> CALL 1-10 START 10");
438         sink.example(L">> CALL 1-10 LENGTH 50");
439 }
440
441 spl::shared_ptr<core::frame_producer> create_producer(const core::frame_producer_dependencies& dependencies, const std::vector<std::wstring>& params)
442 {               
443         auto filename = probe_stem(env::media_folder() + L"/" + params.at(0));
444
445         if(filename.empty())
446                 return core::frame_producer::empty();
447         
448         bool loop                       = contains_param(L"LOOP", params);
449         auto start                      = get_param(L"START", params, get_param(L"SEEK", params, static_cast<uint32_t>(0)));
450         auto length                     = get_param(L"LENGTH", params, std::numeric_limits<uint32_t>::max());
451         auto filter_str         = get_param(L"FILTER", params, L"");
452         auto channel_layout     = get_param(L"CHANNEL_LAYOUT", params, L"");
453
454         return create_destroy_proxy(spl::make_shared_ptr(std::make_shared<ffmpeg_producer>(
455                         dependencies.frame_factory,
456                         dependencies.format_desc,
457                         channel_layout,
458                         filename,
459                         filter_str,
460                         loop,
461                         start,
462                         length)));
463 }
464
465 }}