Commit 95ec0f75 authored by Alexandre Lision's avatar Alexandre Lision

Fix compilation with --disable-video

This commit mutualizes resources for audio and video.
Some components have been renamed:
   - Video{Encoder, DECODER} to Media{Encoder, Decoder}
   - VideoIOHandle to MediaIOHandle (new component)

Refs #64413
parent c8bc5ee3
......@@ -173,7 +173,7 @@ int main(int argc, char *argv [])
#ifdef TOP_BUILDDIR
if (!getenv("CODECS_PATH"))
setenv("CODECS_PATH", TOP_BUILDDIR "/src/audio/codecs", 1);
setenv("CODECS_PATH", TOP_BUILDDIR "/src/media/audio/codecs", 1);
#endif
print_title();
......
......@@ -210,7 +210,7 @@ int main(int argc, char *argv [])
#ifdef TOP_BUILDDIR
if (!getenv("CODECS_PATH"))
setenv("CODECS_PATH", TOP_BUILDDIR "/src/audio/codecs", 1);
setenv("CODECS_PATH", TOP_BUILDDIR "/src/media/audio/codecs", 1);
#endif
print_title();
......
......@@ -9,11 +9,19 @@ SUBDIRS += video
endif
libmedia_la_SOURCES = \
libav_utils.cpp
libav_utils.cpp \
socket_pair.cpp \
media_decoder.cpp \
media_encoder.cpp \
media_io_handle.cpp
noinst_HEADERS = \
libav_utils.h \
libav_deps.h
libav_deps.h \
socket_pair.h \
media_decoder.h \
media_encoder.h \
media_io_handle.h
libmedia_la_LIBADD = \
./audio/libaudio.la
......
......@@ -32,11 +32,16 @@
#include "logger.h"
#include "noncopyable.h"
#include "sip/sdp.h"
#include "video/socket_pair.h"
#ifdef RING_VIDEO
#include "video/video_base.h"
#include "video/video_encoder.h"
#include "video/video_decoder.h"
#endif //RING_VIDEO
#include "socket_pair.h"
#include "libav_deps.h"
#include "media_encoder.h"
#include "media_decoder.h"
#include "media_io_handle.h"
#include "audio/audiobuffer.h"
#include "audio/ringbufferpool.h"
#include "audio/resampler.h"
......@@ -44,29 +49,32 @@
#include <sstream>
namespace ring {
using ring::video::SocketPair;
using ring::video::VideoEncoder;
using ring::video::VideoIOHandle;
using ring::video::VideoEncoderException;
using ring::MediaEncoder;
using ring::MediaDecoder;
using ring::MediaEncoderException;
using ring::MediaIOHandle;
class AudioSender {
public:
AudioSender(const std::string& id,
std::map<std::string, std::string> txArgs,
ring::video::SocketPair& socketPair);
SocketPair& socketPair);
~AudioSender();
private:
NON_COPYABLE(AudioSender);
bool waitForDataEncode(const std::chrono::milliseconds& max_wait) const;
bool setup(ring::video::SocketPair& socketPair);
bool setup(SocketPair& socketPair);
std::string id_;
std::map<std::string, std::string> args_;
const AudioFormat format_;
std::unique_ptr<ring::video::VideoEncoder> audioEncoder_;
std::unique_ptr<ring::video::VideoIOHandle> muxContext_;
std::unique_ptr<ring::MediaEncoder> audioEncoder_;
#ifdef RING_VIDEO
std::unique_ptr<ring::MediaIOHandle> muxContext_;
#endif
std::unique_ptr<ring::Resampler> resampler_;
const double secondsPerPacket_ {0.02}; // 20 ms
......@@ -101,16 +109,20 @@ AudioSender::setup(SocketPair& socketPair)
auto enc_name = args_["codec"].c_str();
auto dest = args_["destination"].c_str();
audioEncoder_.reset(new VideoEncoder);
audioEncoder_.reset(new MediaEncoder);
#ifdef RING_VIDEO
muxContext_.reset(socketPair.createIOContext());
#endif // RING_VIDEO
try {
/* Encoder setup */
audioEncoder_->setOptions(args_);
audioEncoder_->openOutput(enc_name, "rtp", dest, NULL, false);
#ifdef RING_VIDEO
audioEncoder_->setIOContext(muxContext_);
#endif // RING_VIDEO
audioEncoder_->startIO();
} catch (const VideoEncoderException &e) {
} catch (const MediaEncoderException &e) {
RING_ERR("%s", e.what());
return false;
}
......@@ -126,7 +138,9 @@ void
AudioSender::cleanup()
{
audioEncoder_.reset();
#ifdef RING_VIDEO
muxContext_.reset();
#endif // RING_VIDEO
}
void
......@@ -190,7 +204,7 @@ class AudioReceiveThread
public:
AudioReceiveThread(const std::string &id, const std::string &sdp);
~AudioReceiveThread();
void addIOContext(ring::video::SocketPair &socketPair);
void addIOContext(SocketPair &socketPair);
void startLoop();
private:
......@@ -211,9 +225,10 @@ class AudioReceiveThread
/*-----------------------------------------------------------------*/
const std::string id_;
std::istringstream stream_;
std::unique_ptr<ring::video::VideoDecoder> audioDecoder_;
std::unique_ptr<ring::video::VideoIOHandle> sdpContext_;
std::unique_ptr<ring::video::VideoIOHandle> demuxContext_;
std::unique_ptr<ring::MediaDecoder> audioDecoder_;
std::unique_ptr<ring::MediaIOHandle> sdpContext_;
std::unique_ptr<ring::MediaIOHandle> demuxContext_;
std::shared_ptr<ring::RingBuffer> ringbuffer_;
ThreadLoop loop_;
......@@ -225,7 +240,7 @@ class AudioReceiveThread
AudioReceiveThread::AudioReceiveThread(const std::string& id, const std::string& sdp)
: id_(id)
, stream_(sdp)
, sdpContext_(new VideoIOHandle(sdp.size(), false, &readFunction, 0, 0, this))
, sdpContext_(new MediaIOHandle(sdp.size(), false, &readFunction, 0, 0, this))
, loop_(std::bind(&AudioReceiveThread::setup, this),
std::bind(&AudioReceiveThread::process, this),
std::bind(&AudioReceiveThread::cleanup, this))
......@@ -240,7 +255,7 @@ AudioReceiveThread::~AudioReceiveThread()
bool
AudioReceiveThread::setup()
{
audioDecoder_.reset(new ring::video::VideoDecoder());
audioDecoder_.reset(new ring::MediaDecoder());
audioDecoder_->setInterruptCallback(interruptCb, this);
// custom_io so the SDP demuxer will not open any UDP connections
args_["sdp_flags"] = "custom_io";
......@@ -267,12 +282,12 @@ AudioReceiveThread::process()
switch (audioDecoder_->decode_audio(decodedFrame.get())) {
case ring::video::VideoDecoder::Status::FrameFinished:
case ring::MediaDecoder::Status::FrameFinished:
audioDecoder_->writeToRingBuffer(decodedFrame.get(), *ringbuffer_,
mainBuffFormat);
return;
case ring::video::VideoDecoder::Status::DecodeError:
case ring::MediaDecoder::Status::DecodeError:
RING_WARN("decoding failure, trying to reset decoder...");
if (not setup()) {
RING_ERR("fatal error, rx thread re-setup failed");
......@@ -286,7 +301,7 @@ AudioReceiveThread::process()
}
break;
case ring::video::VideoDecoder::Status::ReadError:
case ring::MediaDecoder::Status::ReadError:
RING_ERR("fatal error, read failed");
loop_.stop();
break;
......@@ -430,7 +445,7 @@ AVFormatRtpSession::startSender()
try {
sender_.reset(new AudioSender(id_, txArgs_, *socketPair_));
} catch (const VideoEncoderException &e) {
} catch (const MediaEncoderException &e) {
RING_ERR("%s", e.what());
sending_ = false;
}
......
......@@ -40,16 +40,13 @@
#include <memory>
#include <mutex>
namespace ring { namespace video {
class SocketPair;
class VideoEncoder;
}}
class Sdp;
class ThreadLoop;
class MediaEncoder;
namespace ring {
class SocketPair;
class RingBuffer;
class Resampler;
class AudioSender;
......@@ -78,7 +75,7 @@ class AVFormatRtpSession {
std::string id_;
std::map<std::string, std::string> txArgs_;
std::string receivingSDP_;
std::unique_ptr<ring::video::SocketPair> socketPair_;
std::unique_ptr<ring::SocketPair> socketPair_;
std::unique_ptr<AudioSender> sender_;
std::unique_ptr<AudioReceiveThread> receiveThread_;
std::shared_ptr<ring::RingBuffer> ringbuffer_;
......
......@@ -31,7 +31,8 @@
// libav_deps.h must be included first
#include "libav_deps.h"
#include "video_decoder.h"
#include "media_decoder.h"
#include "media_io_handle.h"
#include "audio/audiobuffer.h"
#include "audio/ringbuffer.h"
#include "audio/resampler.h"
......@@ -40,18 +41,18 @@
#include <iostream>
#include <unistd.h>
namespace ring { namespace video {
namespace ring {
using std::string;
VideoDecoder::VideoDecoder() :
MediaDecoder::MediaDecoder() :
inputCtx_(avformat_alloc_context()),
startTime_(AV_NOPTS_VALUE),
lastDts_(AV_NOPTS_VALUE)
{
}
VideoDecoder::~VideoDecoder()
MediaDecoder::~MediaDecoder()
{
if (decoderCtx_)
avcodec_close(decoderCtx_);
......@@ -66,7 +67,7 @@ VideoDecoder::~VideoDecoder()
}
void
VideoDecoder::extract(const std::map<std::string, std::string>& map, const std::string& key)
MediaDecoder::extract(const std::map<std::string, std::string>& map, const std::string& key)
{
auto iter = map.find(key);
......@@ -75,7 +76,7 @@ VideoDecoder::extract(const std::map<std::string, std::string>& map, const std::
}
void
VideoDecoder::setOptions(const std::map<std::string, std::string>& options)
MediaDecoder::setOptions(const std::map<std::string, std::string>& options)
{
extract(options, "framerate");
extract(options, "video_size");
......@@ -84,7 +85,7 @@ VideoDecoder::setOptions(const std::map<std::string, std::string>& options)
extract(options, "sdp_flags");
}
int VideoDecoder::openInput(const std::string &source_str,
int MediaDecoder::openInput(const std::string &source_str,
const std::string &format_str)
{
AVInputFormat *iformat = av_find_input_format(format_str.c_str());
......@@ -106,7 +107,7 @@ int VideoDecoder::openInput(const std::string &source_str,
return ret;
}
void VideoDecoder::setInterruptCallback(int (*cb)(void*), void *opaque)
void MediaDecoder::setInterruptCallback(int (*cb)(void*), void *opaque)
{
if (cb) {
inputCtx_->interrupt_callback.callback = cb;
......@@ -116,10 +117,10 @@ void VideoDecoder::setInterruptCallback(int (*cb)(void*), void *opaque)
}
}
void VideoDecoder::setIOContext(VideoIOHandle *ioctx)
void MediaDecoder::setIOContext(MediaIOHandle *ioctx)
{ inputCtx_->pb = ioctx->getContext(); }
int VideoDecoder::setupFromAudioData()
int MediaDecoder::setupFromAudioData()
{
int ret;
......@@ -197,7 +198,8 @@ int VideoDecoder::setupFromAudioData()
return 0;
}
int VideoDecoder::setupFromVideoData()
#ifdef RING_VIDEO
int MediaDecoder::setupFromVideoData()
{
int ret;
......@@ -277,8 +279,8 @@ int VideoDecoder::setupFromVideoData()
return 0;
}
VideoDecoder::Status
VideoDecoder::decode(VideoFrame& result, VideoPacket& video_packet)
MediaDecoder::Status
MediaDecoder::decode(ring::video::VideoFrame& result, ring::video::VideoPacket& video_packet)
{
AVPacket *inpacket = video_packet.get();
int ret = av_read_frame(inputCtx_, inpacket);
......@@ -328,9 +330,10 @@ VideoDecoder::decode(VideoFrame& result, VideoPacket& video_packet)
return Status::Success;
}
#endif // RING_VIDEO
VideoDecoder::Status
VideoDecoder::decode_audio(AVFrame *decoded_frame)
MediaDecoder::Status
MediaDecoder::decode_audio(AVFrame *decoded_frame)
{
AVPacket inpacket;
memset(&inpacket, 0, sizeof(inpacket));
......@@ -386,8 +389,9 @@ VideoDecoder::decode_audio(AVFrame *decoded_frame)
return Status::Success;
}
VideoDecoder::Status
VideoDecoder::flush(VideoFrame& result)
#ifdef RING_VIDEO
MediaDecoder::Status
MediaDecoder::flush(ring::video::VideoFrame& result)
{
AVPacket inpacket;
memset(&inpacket, 0, sizeof(inpacket));
......@@ -406,17 +410,18 @@ VideoDecoder::flush(VideoFrame& result)
return Status::Success;
}
#endif // RING_VIDEO
int VideoDecoder::getWidth() const
int MediaDecoder::getWidth() const
{ return decoderCtx_->width; }
int VideoDecoder::getHeight() const
int MediaDecoder::getHeight() const
{ return decoderCtx_->height; }
int VideoDecoder::getPixelFormat() const
int MediaDecoder::getPixelFormat() const
{ return libav_utils::sfl_pixel_format(decoderCtx_->pix_fmt); }
void VideoDecoder::writeToRingBuffer(AVFrame* decoded_frame,
void MediaDecoder::writeToRingBuffer(AVFrame* decoded_frame,
ring::RingBuffer& rb,
const ring::AudioFormat outFormat)
{
......@@ -444,4 +449,4 @@ void VideoDecoder::writeToRingBuffer(AVFrame* decoded_frame,
}
}
}}
}
......@@ -29,33 +29,47 @@
* as that of the covered work.
*/
#ifndef __VIDEO_DECODER_H__
#define __VIDEO_DECODER_H__
#ifndef __MEDIA_DECODER_H__
#define __MEDIA_DECODER_H__
#include "config.h"
#ifdef RING_VIDEO
#include "video/video_base.h"
#include "video/video_scaler.h"
#endif // RING_VIDEO
#include "video_base.h"
#include "video_scaler.h"
#include "noncopyable.h"
#include <map>
#include <string>
#include <memory>
namespace ring {
class AudioBuffer;
class AudioFormat;
class RingBuffer;
class Resampler;
}
#include <chrono>
class AVCodecContext;
class AVStream;
class AVFrame;
class AVDictionary;
class AVFormatContext;
class AVCodec;
#ifdef RING_VIDEO
namespace ring { namespace video {
class VideoFrame;
class VideoPacket;
}}
#endif // RING_VIDEO
class VideoDecoder {
public:
namespace ring {
class AudioBuffer;
class AudioFormat;
class RingBuffer;
class Resampler;
class MediaIOHandle;
class MediaDecoder {
public:
enum class Status {
Success,
FrameFinished,
......@@ -64,21 +78,25 @@ namespace ring { namespace video {
DecodeError
};
VideoDecoder();
~VideoDecoder();
MediaDecoder();
~MediaDecoder();
void emulateRate() { emulateRate_ = true; }
void setInterruptCallback(int (*cb)(void*), void *opaque);
void setIOContext(VideoIOHandle *ioctx);
int openInput(const std::string &source_str,
const std::string &format_str);
void setIOContext(MediaIOHandle *ioctx);
#ifdef RING_VIDEO
int setupFromVideoData();
Status decode(ring::video::VideoFrame&, ring::video::VideoPacket&);
Status flush(ring::video::VideoFrame&);
#endif // RING_VIDEO
int setupFromAudioData();
Status decode(VideoFrame&, VideoPacket&);
Status decode_audio(AVFrame* frame);
void writeToRingBuffer(AVFrame* frame, ring::RingBuffer& rb,
const ring::AudioFormat outFormat);
Status flush(VideoFrame&);
int getWidth() const;
int getHeight() const;
......@@ -87,7 +105,7 @@ namespace ring { namespace video {
void setOptions(const std::map<std::string, std::string>& options);
private:
NON_COPYABLE(VideoDecoder);
NON_COPYABLE(MediaDecoder);
AVCodec *inputDecoder_ = nullptr;
AVCodecContext *decoderCtx_ = nullptr;
......@@ -104,6 +122,6 @@ namespace ring { namespace video {
protected:
AVDictionary *options_ = nullptr;
};
}}
}
#endif // __VIDEO_DECODER_H__
#endif // __MEDIA_DECODER_H__
......@@ -30,7 +30,8 @@
*/
#include "libav_deps.h"
#include "video_encoder.h"
#include "media_encoder.h"
#include "media_io_handle.h"
#include "audio/audiobuffer.h"
#include "logger.h"
......@@ -39,17 +40,19 @@
#include <algorithm>
namespace ring { namespace video {
namespace ring {
using std::string;
VideoEncoder::VideoEncoder() :
outputCtx_(avformat_alloc_context()),
MediaEncoder::MediaEncoder() :
#ifdef RING_VIDEO
scaler_(),
scaledFrame_()
scaledFrame_(),
#endif // RING_VIDEO
outputCtx_(avformat_alloc_context())
{}
VideoEncoder::~VideoEncoder()
MediaEncoder::~MediaEncoder()
{
if (outputCtx_ and outputCtx_->priv_data)
av_write_trailer(outputCtx_);
......@@ -75,7 +78,7 @@ extract(const std::map<std::string, std::string>& map, const std::string& key)
return iter->second.c_str();
}
void VideoEncoder::setOptions(const std::map<std::string, std::string>& options)
void MediaEncoder::setOptions(const std::map<std::string, std::string>& options)
{
const char *value;
......@@ -117,14 +120,14 @@ void VideoEncoder::setOptions(const std::map<std::string, std::string>& options)
}
void
VideoEncoder::openOutput(const char *enc_name, const char *short_name,
MediaEncoder::openOutput(const char *enc_name, const char *short_name,
const char *filename, const char *mime_type, bool is_video)
{
AVOutputFormat *oformat = av_guess_format(short_name, filename, mime_type);
if (!oformat) {
RING_ERR("Unable to find a suitable output format for %s", filename);
throw VideoEncoderException("No output format");
throw MediaEncoderException("No output format");
}
outputCtx_->oformat = oformat;
......@@ -136,7 +139,7 @@ VideoEncoder::openOutput(const char *enc_name, const char *short_name,
outputEncoder_ = avcodec_find_encoder_by_name(enc_name);
if (!outputEncoder_) {
RING_ERR("Encoder \"%s\" not found!", enc_name);
throw VideoEncoderException("No output encoder");
throw MediaEncoderException("No output encoder");
}
prepareEncoderContext(is_video);
......@@ -161,7 +164,7 @@ VideoEncoder::openOutput(const char *enc_name, const char *short_name,
ret = avcodec_open2(encoderCtx_, outputEncoder_, NULL);
#endif
if (ret)
throw VideoEncoderException("Could not open encoder");
throw MediaEncoderException("Could not open encoder");
// add video stream to outputformat context
#if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(53, 8, 0)
......@@ -170,10 +173,10 @@ VideoEncoder::openOutput(const char *enc_name, const char *short_name,
stream_ = avformat_new_stream(outputCtx_, 0);
#endif
if (!stream_)
throw VideoEncoderException("Could not allocate stream");
throw MediaEncoderException("Could not allocate stream");
stream_->codec = encoderCtx_;
#ifdef RING_VIDEO
if (is_video) {
// allocate buffers for both scaled (pre-encoder) and encoded frames
const int width = encoderCtx_->width;
......@@ -181,24 +184,25 @@ VideoEncoder::openOutput(const char *enc_name, const char *short_name,
const int format = libav_utils::sfl_pixel_format((int)encoderCtx_->pix_fmt);
scaledFrameBufferSize_ = scaledFrame_.getSize(width, height, format);
if (scaledFrameBufferSize_ <= FF_MIN_BUFFER_SIZE)
throw VideoEncoderException("buffer too small");
throw MediaEncoderException("buffer too small");
#if (LIBAVCODEC_VERSION_MAJOR < 54)
encoderBufferSize_ = scaledFrameBufferSize_; // seems to be ok
encoderBuffer_ = (uint8_t*) av_malloc(encoderBufferSize_);
if (!encoderBuffer_)
throw VideoEncoderException("Could not allocate encoder buffer");
throw MediaEncoderException("Could not allocate encoder buffer");
#endif
scaledFrameBuffer_ = (uint8_t*) av_malloc(scaledFrameBufferSize_);
if (!scaledFrameBuffer_)
throw VideoEncoderException("Could not allocate scaled frame buffer");
throw MediaEncoderException("Could not allocate scaled frame buffer");
scaledFrame_.setDestination(scaledFrameBuffer_, width, height, format);
}
#endif // RING_VIDEO
}
void VideoEncoder::setInterruptCallback(int (*cb)(void*), void *opaque)
void MediaEncoder::setInterruptCallback(int (*cb)(void*), void *opaque)
{
if (