-namespace caspar {\r
- \r
-static const size_t PACKET_BUFFER_COUNT = 100; // Assume that av_read_frame distance between audio and video packets is less than PACKET_BUFFER_COUNT.\r
-\r
-class stream\r
-{\r
- std::shared_ptr<AVCodecContext> ctx_;\r
- int index_;\r
- tbb::concurrent_bounded_queue<std::shared_ptr<AVPacket>> buffer_;\r
-\r
-public:\r
-\r
- stream()\r
- : index_(-1)\r
- {\r
- buffer_.set_capacity(PACKET_BUFFER_COUNT);\r
- }\r
-\r
- int open(std::shared_ptr<AVFormatContext>& fctx, AVMediaType media_type)\r
- { \r
- const auto streams = boost::iterator_range<AVStream**>(fctx->streams, fctx->streams+fctx->nb_streams);\r
- const auto stream = boost::find_if(streams, [&](AVStream* stream) \r
- {\r
- return stream && stream->codec->codec_type == media_type;\r
- });\r
- \r
- if(stream == streams.end()) \r
- return AVERROR_STREAM_NOT_FOUND;\r
- \r
- auto codec = avcodec_find_decoder((*stream)->codec->codec_id); \r
- if(!codec)\r
- return AVERROR_DECODER_NOT_FOUND;\r
- \r
- index_ = (*stream)->index;\r
-\r
- int errn = tbb_avcodec_open((*stream)->codec, codec);\r
- if(errn >= 0)\r
- {\r
- ctx_.reset((*stream)->codec, tbb_avcodec_close);\r
-\r
- // Some files give an invalid time_base numerator, try to fix it.\r
- if(ctx_ && ctx_->time_base.num == 1)\r
- ctx_->time_base.num = static_cast<int>(std::pow(10.0, static_cast<int>(std::log10(static_cast<float>(ctx_->time_base.den)))-1));\r
- }\r
- return errn; \r
- }\r
-\r
- bool try_pop(std::shared_ptr<AVPacket>& pkt)\r
- {\r
- return buffer_.try_pop(pkt);\r
- }\r
-\r
- void push(const std::shared_ptr<AVPacket>& pkt)\r
- {\r
- if(pkt->stream_index != index_)\r
- return;\r
-\r
- av_dup_packet(pkt.get());\r
- buffer_.push(pkt); \r
- }\r
-\r
- void flush()\r
- {\r
- if(index_ == -1)\r
- return;\r
-\r
- std::shared_ptr<AVPacket> flsh_pkt(new AVPacket);\r
- flsh_pkt->size = 0;\r
- buffer_.push(flsh_pkt); \r
- }\r
-\r
- const std::shared_ptr<AVCodecContext>& ctx() { return ctx_; }\r
-\r
- operator bool(){return ctx_ != nullptr;}\r
-\r
- double fps() const { return !ctx_ ? -1.0 : static_cast<double>(ctx_->time_base.den) / static_cast<double>(ctx_->time_base.num); }\r