]> git.sesse.net Git - casparcg/blob - modules/ffmpeg/producer/video/video_decoder.cpp
[ffmpeg_producer] Resolved problem where video decoders having CODEC_CAP_DELAY needs...
[casparcg] / modules / ffmpeg / producer / video / video_decoder.cpp
1 /*
2 * Copyright 2013 Sveriges Television AB http://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 "video_decoder.h"
25
26 #include "../util/util.h"
27
28 #include "../../ffmpeg_error.h"
29
30 #include <core/frame/frame_transform.h>
31 #include <core/frame/frame_factory.h>
32
33 #include <boost/range/algorithm_ext/push_back.hpp>
34 #include <boost/filesystem.hpp>
35
36 #include <queue>
37
38 #if defined(_MSC_VER)
39 #pragma warning (push)
40 #pragma warning (disable : 4244)
41 #endif
42 extern "C"
43 {
44         #include <libavcodec/avcodec.h>
45         #include <libavformat/avformat.h>
46 }
47 #if defined(_MSC_VER)
48 #pragma warning (pop)
49 #endif
50
51 namespace caspar { namespace ffmpeg {
52
53 struct video_decoder::implementation : boost::noncopyable
54 {
55         int                                                                             index_                          = -1;
56         const spl::shared_ptr<AVCodecContext>   codec_context_;
57
58         std::queue<spl::shared_ptr<AVPacket>>   packets_;
59
60         const uint32_t                                                  nb_frames_;
61
62         const int                                                               width_                          = codec_context_->width;
63         const int                                                               height_                         = codec_context_->height;
64         bool                                                                    is_progressive_;
65
66         tbb::atomic<uint32_t>                                   file_frame_number_;
67
68 public:
69         explicit implementation(const spl::shared_ptr<AVFormatContext>& context)
70                 : codec_context_(open_codec(*context, AVMEDIA_TYPE_VIDEO, index_, false))
71                 , nb_frames_(static_cast<uint32_t>(context->streams[index_]->nb_frames))
72         {
73                 file_frame_number_ = 0;
74
75                 codec_context_->refcounted_frames = 1;
76         }
77
78         void push(const std::shared_ptr<AVPacket>& packet)
79         {
80                 if(!packet)
81                         return;
82
83                 if(packet->stream_index == index_ || packet->data == nullptr)
84                         packets_.push(spl::make_shared_ptr(packet));
85         }
86
87         std::shared_ptr<AVFrame> poll()
88         {
89                 if(packets_.empty())
90                         return nullptr;
91
92                 auto packet = packets_.front();
93
94                 if(packet->data == nullptr)
95                 {
96                         if(codec_context_->codec->capabilities & CODEC_CAP_DELAY)
97                         {
98                                 auto video = decode(packet);
99                                 if(video)
100                                         return video;
101                         }
102
103                         packets_.pop();
104
105                         if (packet->pos != -1)
106                         {
107                                 file_frame_number_ = static_cast<uint32_t>(packet->pos);
108                                 avcodec_flush_buffers(codec_context_.get());
109                                 return flush_video();
110                         }
111                         else // Really EOF
112                                 return nullptr;
113                 }
114
115                 packets_.pop();
116                 return decode(packet);
117         }
118
119         std::shared_ptr<AVFrame> decode(spl::shared_ptr<AVPacket> pkt)
120         {
121                 auto decoded_frame = create_frame();
122
123                 int frame_finished = 0;
124                 THROW_ON_ERROR2(avcodec_decode_video2(codec_context_.get(), decoded_frame.get(), &frame_finished, pkt.get()), "[video_decoder]");
125
126                 // If a decoder consumes less then the whole packet then something is wrong
127                 // that might be just harmless padding at the end, or a problem with the
128                 // AVParser or demuxer which puted more then one frame in a AVPacket.
129
130                 if(frame_finished == 0)
131                         return nullptr;
132
133                 is_progressive_ = !decoded_frame->interlaced_frame;
134
135                 if(decoded_frame->repeat_pict > 0)
136                         CASPAR_LOG(warning) << "[video_decoder] Field repeat_pict not implemented.";
137
138                 ++file_frame_number_;
139
140                 // This ties the life of the decoded_frame to the packet that it came from. For the
141                 // current version of ffmpeg (0.8 or c17808c) the RAW_VIDEO codec returns frame data
142                 // owned by the packet.
143                 return std::shared_ptr<AVFrame>(decoded_frame.get(), [decoded_frame, pkt](AVFrame*){});
144         }
145
146         bool ready() const
147         {
148                 return packets_.size() >= 8;
149         }
150
151         uint32_t nb_frames() const
152         {
153                 return std::max(nb_frames_, static_cast<uint32_t>(file_frame_number_));
154         }
155
156         std::wstring print() const
157         {
158                 return L"[video-decoder] " + u16(codec_context_->codec->long_name);
159         }
160 };
161
162 video_decoder::video_decoder(const spl::shared_ptr<AVFormatContext>& context) : impl_(new implementation(context)){}
163 void video_decoder::push(const std::shared_ptr<AVPacket>& packet){impl_->push(packet);}
164 std::shared_ptr<AVFrame> video_decoder::poll(){return impl_->poll();}
165 bool video_decoder::ready() const{return impl_->ready();}
166 int video_decoder::width() const{return impl_->width_;}
167 int video_decoder::height() const{return impl_->height_;}
168 uint32_t video_decoder::nb_frames() const{return impl_->nb_frames();}
169 uint32_t video_decoder::file_frame_number() const{return static_cast<uint32_t>(impl_->file_frame_number_);}
170 bool    video_decoder::is_progressive() const{return impl_->is_progressive_;}
171 std::wstring video_decoder::print() const{return impl_->print();}
172
173 }}