Skip to content
Snippets Groups Projects
Commit f1f0608f authored by Philippe Gorley's avatar Philippe Gorley Committed by Guillaume Roguez
Browse files

media: modify stream setup


Merges setupFromAudioData and setupFromVideoData to reduce redundancy

Change-Id: Id543d0775a7803b778796b9abc02c9decd2c7e15
Reviewed-by: default avatarGuillaume Roguez <guillaume.roguez@savoirfairelinux.com>
parent 0956c1d5
Branches
No related tags found
No related merge requests found
...@@ -33,7 +33,8 @@ noinst_HEADERS = \ ...@@ -33,7 +33,8 @@ noinst_HEADERS = \
media_codec.h \ media_codec.h \
system_codec_container.h \ system_codec_container.h \
srtp.h \ srtp.h \
recordable.h recordable.h \
decoder_finder.h
libmedia_la_LIBADD = \ libmedia_la_LIBADD = \
./audio/libaudio.la ./audio/libaudio.la
......
...@@ -23,7 +23,7 @@ extern "C" { ...@@ -23,7 +23,7 @@ extern "C" {
#include <libavcodec/avcodec.h> #include <libavcodec/avcodec.h>
} }
namespace ring { namespace video { namespace ring {
/** /**
* Attempt to find standalone AVCodec decoder using AVCodecID, * Attempt to find standalone AVCodec decoder using AVCodecID,
...@@ -57,4 +57,4 @@ findDecoder(const enum AVCodecID codec_id) ...@@ -57,4 +57,4 @@ findDecoder(const enum AVCodecID codec_id)
return codec; return codec;
} }
}} // namespace ring::video } // namespace ring
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
#include "audio/audiobuffer.h" #include "audio/audiobuffer.h"
#include "audio/ringbuffer.h" #include "audio/ringbuffer.h"
#include "audio/resampler.h" #include "audio/resampler.h"
#include "video/decoder_finder.h" #include "decoder_finder.h"
#include "manager.h" #include "manager.h"
#ifdef RING_ACCEL #ifdef RING_ACCEL
...@@ -148,169 +148,71 @@ void MediaDecoder::setIOContext(MediaIOHandle *ioctx) ...@@ -148,169 +148,71 @@ void MediaDecoder::setIOContext(MediaIOHandle *ioctx)
int MediaDecoder::setupFromAudioData(const AudioFormat format) int MediaDecoder::setupFromAudioData(const AudioFormat format)
{ {
int ret; // Use AVDictionary to send extra arguments to setupStream, since video setup doesn't need them
av_dict_set_int(&options_, "nb_channels", format.nb_channels, 0);
if (decoderCtx_) av_dict_set_int(&options_, "sample_rate", format.sample_rate, 0);
avcodec_close(decoderCtx_); return setupStream(AVMEDIA_TYPE_AUDIO);
// Increase analyze time to solve synchronization issues between callers.
static const unsigned MAX_ANALYZE_DURATION = 30; // time in seconds
inputCtx_->max_analyze_duration = MAX_ANALYZE_DURATION * AV_TIME_BASE;
RING_DBG("Finding stream info");
ret = avformat_find_stream_info(inputCtx_, NULL);
RING_DBG("Finding stream info DONE");
if (ret < 0) {
char errBuf[64] = {0};
// print nothing for unknown errors
if (av_strerror(ret, errBuf, sizeof errBuf) < 0)
errBuf[0] = '\0';
// always fail here
RING_ERR("Could not find stream info: %s", errBuf);
return -1;
}
// find the first audio stream from the input
for (size_t i = 0; streamIndex_ == -1 && i < inputCtx_->nb_streams; ++i)
#ifndef _WIN32
if (inputCtx_->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
#else
if (inputCtx_->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO)
#endif
streamIndex_ = i;
if (streamIndex_ == -1) {
RING_ERR("Could not find audio stream");
return -1;
}
// Get a pointer to the codec context for the video stream
avStream_ = inputCtx_->streams[streamIndex_];
#ifndef _WIN32
inputDecoder_ = avcodec_find_decoder(avStream_->codecpar->codec_id);
if (!inputDecoder_) {
RING_ERR("Unsupported codec");
return -1;
}
decoderCtx_ = avcodec_alloc_context3(inputDecoder_);
avcodec_parameters_to_context(decoderCtx_, avStream_->codecpar);
#else
decoderCtx_ = avStream_->codec;
if (decoderCtx_ == 0) {
RING_ERR("Decoder context is NULL");
return -1;
}
// find the decoder for the audio stream
inputDecoder_ = avcodec_find_decoder(decoderCtx_->codec_id);
if (!inputDecoder_) {
RING_ERR("Unsupported codec");
return -1;
}
#endif
decoderCtx_->thread_count = std::max(1u, std::min(8u, std::thread::hardware_concurrency()/2));
decoderCtx_->channels = format.nb_channels;
decoderCtx_->sample_rate = format.sample_rate;
RING_DBG("Audio decoding using %s with %s",
inputDecoder_->name, format.toString().c_str());
if (emulateRate_) {
RING_DBG("Using framerate emulation");
startTime_ = av_gettime();
}
ret = avcodec_open2(decoderCtx_, inputDecoder_, NULL);
if (ret) {
RING_ERR("Could not open codec");
return -1;
} }
return 0; int
} MediaDecoder::setupStream(AVMediaType mediaType)
#ifdef RING_VIDEO
int MediaDecoder::setupFromVideoData()
{ {
int ret = 0; int ret = 0;
std::string streamType = av_get_media_type_string(mediaType);
if (decoderCtx_) avcodec_free_context(&decoderCtx_);
avcodec_close(decoderCtx_);
// Increase analyze time to solve synchronization issues between callers. // Increase analyze time to solve synchronization issues between callers.
static const unsigned MAX_ANALYZE_DURATION = 30; // time in seconds static const unsigned MAX_ANALYZE_DURATION = 30;
inputCtx_->max_analyze_duration = MAX_ANALYZE_DURATION * AV_TIME_BASE; inputCtx_->max_analyze_duration = MAX_ANALYZE_DURATION * AV_TIME_BASE;
// if fallback from accel, don't check for stream info, it's already done
// If fallback from accel, don't check for stream info, it's already done
if (!fallback_) { if (!fallback_) {
RING_DBG("Finding stream info"); RING_DBG() << "Finding " << streamType << " stream info";
ret = avformat_find_stream_info(inputCtx_, NULL); if ((ret = avformat_find_stream_info(inputCtx_, nullptr)) < 0) {
} char errBuf[64];
if (ret < 0) { av_strerror(ret, errBuf, sizeof(errBuf));
// workaround for this bug:
// http://patches.libav.org/patch/22541/ // Always fail here
if (ret == -1) RING_ERR() << "Could not find " << streamType << " stream info: " << errBuf;
ret = AVERROR_INVALIDDATA;
char errBuf[64] = {0};
// print nothing for unknown errors
if (av_strerror(ret, errBuf, sizeof errBuf) < 0)
errBuf[0] = '\0';
// always fail here
RING_ERR("Could not find stream info: %s", errBuf);
return -1; return -1;
} }
}
// find the first video stream from the input for (size_t i = 0; streamIndex_ == -1 && i < inputCtx_->nb_streams; ++i) {
for (size_t i = 0; streamIndex_ == -1 && i < inputCtx_->nb_streams; ++i) if (inputCtx_->streams[i]->codecpar->codec_type == mediaType) {
#ifndef _WIN32
if (inputCtx_->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
#else
if (inputCtx_->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO)
#endif
streamIndex_ = i; streamIndex_ = i;
}
}
if (streamIndex_ == -1) { if (streamIndex_ < 0) {
RING_ERR("Could not find video stream"); RING_ERR() << "No " << streamType << " stream found";
return -1; return -1;
} }
// Get a pointer to the codec context for the video stream
avStream_ = inputCtx_->streams[streamIndex_]; avStream_ = inputCtx_->streams[streamIndex_];
#ifndef _WIN32
inputDecoder_ = video::findDecoder(avStream_->codecpar->codec_id); inputDecoder_ = findDecoder(avStream_->codecpar->codec_id);
if (!inputDecoder_) { if (!inputDecoder_) {
RING_ERR("Unsupported codec"); RING_ERR() << "Unsupported codec";
return -1; return -1;
} }
decoderCtx_ = avcodec_alloc_context3(inputDecoder_); decoderCtx_ = avcodec_alloc_context3(inputDecoder_);
avcodec_parameters_to_context(decoderCtx_, avStream_->codecpar); if (!decoderCtx_) {
#else RING_ERR() << "Failed to create decoder context";
decoderCtx_ = avStream_->codec;
if (decoderCtx_ == 0) {
RING_ERR("Decoder context is NULL");
return -1; return -1;
} }
avcodec_parameters_to_context(decoderCtx_, avStream_->codecpar);
// find the decoder for the video stream
inputDecoder_ = avcodec_find_decoder(decoderCtx_->codec_id);
if (!inputDecoder_) {
RING_ERR("Unsupported codec");
return -1;
}
#endif
RING_DBG("Decoding video using %s (%s)", inputDecoder_->long_name, inputDecoder_->name);
decoderCtx_->thread_count = std::max(1u, std::min(8u, std::thread::hardware_concurrency()/2)); decoderCtx_->thread_count = std::max(1u, std::min(8u, std::thread::hardware_concurrency()/2));
if (mediaType == AVMEDIA_TYPE_AUDIO) {
decoderCtx_->channels = std::stoi(av_dict_get(options_, "nb_channels", nullptr, 0)->value);
decoderCtx_->sample_rate = std::stoi(av_dict_get(options_, "sample_rate", nullptr, 0)->value);
}
if (emulateRate_) { if (emulateRate_) {
RING_DBG("Using framerate emulation"); RING_DBG() << "Using framerate emulation";
startTime_ = av_gettime(); startTime_ = av_gettime();
} }
...@@ -319,21 +221,31 @@ int MediaDecoder::setupFromVideoData() ...@@ -319,21 +221,31 @@ int MediaDecoder::setupFromVideoData()
accel_ = video::setupHardwareDecoding(decoderCtx_); accel_ = video::setupHardwareDecoding(decoderCtx_);
decoderCtx_->opaque = &accel_; decoderCtx_->opaque = &accel_;
} else if (Manager::instance().getDecodingAccelerated()) { } else if (Manager::instance().getDecodingAccelerated()) {
RING_WARN("Hardware accelerated decoding disabled because of previous failure"); RING_WARN() << "Hardware accelerated decoding disabled because of previous failure";
} else { } else {
RING_WARN("Hardware accelerated decoding disabled by user preference"); RING_WARN() << "Hardware accelerated decoding disabled by user preference";
} }
#endif #endif
ret = avcodec_open2(decoderCtx_, inputDecoder_, NULL); RING_DBG() << "Decoding " << streamType << " using " << inputDecoder_->long_name << " (" << inputDecoder_->name << ")";
if (ret) {
RING_ERR("Could not open codec"); ret = avcodec_open2(decoderCtx_, inputDecoder_, nullptr);
if (ret < 0) {
char errBuf[64];
av_strerror(ret, errBuf, sizeof(errBuf));
RING_ERR() << "Could not open codec: " << errBuf;
return -1; return -1;
} }
return 0; return 0;
} }
#ifdef RING_VIDEO
int MediaDecoder::setupFromVideoData()
{
return setupStream(AVMEDIA_TYPE_VIDEO);
}
MediaDecoder::Status MediaDecoder::Status
MediaDecoder::decode(VideoFrame& result) MediaDecoder::decode(VideoFrame& result)
{ {
......
...@@ -45,6 +45,7 @@ class AVStream; ...@@ -45,6 +45,7 @@ class AVStream;
class AVDictionary; class AVDictionary;
class AVFormatContext; class AVFormatContext;
class AVCodec; class AVCodec;
enum AVMediaType;
namespace ring { namespace ring {
...@@ -115,6 +116,7 @@ class MediaDecoder { ...@@ -115,6 +116,7 @@ class MediaDecoder {
void extract(const std::map<std::string, std::string>& map, const std::string& key); void extract(const std::map<std::string, std::string>& map, const std::string& key);
int correctPixFmt(int input_pix_fmt); int correctPixFmt(int input_pix_fmt);
int setupStream(AVMediaType mediaType);
bool fallback_ = false; bool fallback_ = false;
......
...@@ -36,8 +36,7 @@ libvideo_la_SOURCES = \ ...@@ -36,8 +36,7 @@ libvideo_la_SOURCES = \
video_receive_thread.cpp video_receive_thread.h \ video_receive_thread.cpp video_receive_thread.h \
video_sender.cpp video_sender.h \ video_sender.cpp video_sender.h \
video_rtp_session.cpp video_rtp_session.h \ video_rtp_session.cpp video_rtp_session.h \
sinkclient.cpp sinkclient.h \ sinkclient.cpp sinkclient.h
decoder_finder.h
if RING_ACCEL if RING_ACCEL
libvideo_la_SOURCES += accel.cpp accel.h libvideo_la_SOURCES += accel.cpp accel.h
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment