-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() : 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 it = boost::find_if(streams, [&](AVStream* stream) \r
- {\r
- return stream && stream->codec->codec_type == media_type;\r
- });\r
- \r
- if(it == streams.end()) \r
- return AVERROR_STREAM_NOT_FOUND;\r
- \r
- auto codec = avcodec_find_decoder((*it)->codec->codec_id); \r
- if(!codec)\r
- return AVERROR_DECODER_NOT_FOUND;\r
- \r
- index_ = (*it)->index;\r
-\r
- int errn = tbb_avcodec_open((*it)->codec, codec);\r
- if(errn >= 0)\r
- {\r
- ctx_.reset((*it)->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 && pkt->stream_index != index_)\r
- return;\r
-\r
- if(pkt)\r
- av_dup_packet(pkt.get());\r