Commit abb371ec authored by Guillaume Roguez's avatar Guillaume Roguez

#29027: implement video scaler and libav deps removal.

- fix also some Copyright dates.
parent 1a32be8c
......@@ -4,18 +4,21 @@ SUBDIRS=test
noinst_LTLIBRARIES = libvideo.la
libvideo_la_SOURCES = \
libav_utils.cpp libav_utils.h video_rtp_session.cpp \
video_rtp_session.h video_send_thread.h video_send_thread.cpp \
video_receive_thread.h video_receive_thread.cpp \
video_preview.h video_preview.cpp video_v4l2.cpp \
video_v4l2.cpp \
video_v4l2_list.cpp video_v4l2.h video_v4l2_list.h \
video_preferences.h video_preferences.cpp \
check.h shm_header.h \
shm_sink.cpp shm_sink.h video_provider.h \
socket_pair.cpp socket_pair.h \
video_preferences.cpp video_preferences.h \
video_base.cpp video_base.h \
video_scaler.cpp video_scaler.h \
video_decoder.cpp video_decoder.h \
video_encoder.cpp video_encoder.h \
video_codec.h
socket_pair.cpp socket_pair.h \
shm_sink.cpp shm_sink.h \
video_preview.cpp video_preview.h \
video_receive_thread.cpp video_receive_thread.h \
video_send_thread.cpp video_send_thread.h \
video_rtp_session.cpp video_rtp_session.h \
check.h shm_header.h video_provider.h \
libav_utils.cpp libav_utils.h libav_deps.h
libvideo_la_LIBADD = @LIBAVCODEC_LIBS@ @LIBAVFORMAT_LIBS@ @LIBAVDEVICE_LIBS@ @LIBSWSCALE_LIBS@ @LIBAVUTIL_LIBS@ @UDEV_LIBS@
......
/*
* Copyright (C) 2013 Savoir-Faire Linux Inc.
* Author: Guillaume Roguez <Guillaume.Roguez@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Additional permission under GNU GPL version 3 section 7:
*
* If you modify this program, or any covered work, by linking or
* combining it with the OpenSSL project's OpenSSL library (or a
* modified version of that library), containing parts covered by the
* terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc.
* grants you additional permission to convey the resulting work.
* Corresponding Source for a non-source form of such a combination
* shall include the source code for the parts of OpenSSL used as well
* as that of the covered work.
*/
#ifndef __LIBAV_DEPS_H__
#define __LIBAV_DEPS_H__
extern "C" {
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavdevice/avdevice.h>
#include <libswscale/swscale.h>
#include <libavutil/opt.h>
}
#include "libav_utils.h"
/* LIBAVFORMAT_VERSION_CHECK checks for the right version of libav and FFmpeg
* a is the major version
* b and c the minor and micro versions of libav
* d and e the minor and micro versions of FFmpeg */
#define LIBAVFORMAT_VERSION_CHECK( a, b, c, d, e ) \
( (LIBAVFORMAT_VERSION_MICRO < 100 && LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT( a, b, c ) ) || \
(LIBAVFORMAT_VERSION_MICRO >= 100 && LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT( a, d, e ) ) )
#define HAVE_SDP_CUSTOM_IO LIBAVFORMAT_VERSION_CHECK(54,20,3,59,103)
#endif // __LIBAV_DEPS_H__
/*
* Copyright (C) 2004-2012 Savoir-Faire Linux Inc.
* Copyright (C) 2004-2013 Savoir-Faire Linux Inc.
* Author: Tristan Matthews <tristan.matthews@savoirfairelinux.com>
* Author: Luca Barbato <lu_zero@gentoo.org>
* Author: Guillaume Roguez <Guillaume.Roguez@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
......@@ -29,18 +30,15 @@
* as that of the covered work.
*/
#include "libav_utils.h"
#include "libav_deps.h"
#include "video_base.h"
#include "logger.h"
#include <vector>
#include <algorithm>
#include <string>
#include <iostream>
#include "logger.h"
extern "C" {
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavdevice/avdevice.h>
}
namespace {
using std::string;
......@@ -174,4 +172,28 @@ getDefaultCodecs()
return result;
}
int libav_pixel_format(int fmt)
{
switch (fmt) {
case VIDEO_PIXFMT_BGRA: return PIX_FMT_BGRA;
}
return fmt;
}
int sfl_pixel_format(int fmt)
{
switch (fmt) {
case PIX_FMT_BGRA: return VIDEO_PIXFMT_BGRA;
}
return fmt;
}
void sfl_url_split(const char *url,
char *hostname, size_t hostname_size, int *port,
char *path, size_t path_size)
{
av_url_split(NULL, 0, NULL, 0, hostname, hostname_size, port,
path, path_size, url);
}
} // end namespace libav_utils
......@@ -35,20 +35,25 @@
#include <map>
#include <string>
namespace libav_utils {
void
sfl_avcodec_init();
void sfl_avcodec_init();
int libav_pixel_format(int fmt);
int sfl_pixel_format(int fmt);
std::map<std::string, std::string>
encodersMap();
std::map<std::string, std::string> encodersMap();
std::vector<std::string>
getVideoCodecList();
std::vector<std::string> getVideoCodecList();
std::vector<std::map <std::string, std::string> > getDefaultCodecs();
std::vector<std::map<std::string, std::string> >
getDefaultCodecs();
const char *const DEFAULT_H264_PROFILE_LEVEL_ID = "profile-level-id=428014";
const char *const MAX_H264_PROFILE_LEVEL_ID = "profile-level-id=640034";
void sfl_url_split(const char *url,
char *hostname, size_t hostname_size, int *port,
char *path, size_t path_size);
}
#endif // __LIBAV_UTILS_H__
......@@ -62,8 +62,7 @@ SHMSink::~SHMSink()
stop();
}
bool
SHMSink::start()
bool SHMSink::start()
{
if (fd_ != -1) {
ERROR("fd must be -1");
......@@ -123,8 +122,7 @@ SHMSink::start()
return true;
}
bool
SHMSink::stop()
bool SHMSink::stop()
{
if (fd_ >= 0)
close(fd_);
......@@ -143,8 +141,7 @@ SHMSink::stop()
return true;
}
bool
SHMSink::resize_area(size_t desired_length)
bool SHMSink::resize_area(size_t desired_length)
{
if (desired_length < shm_area_len_)
return true;
......
......@@ -30,9 +30,12 @@
* as that of the covered work.
*/
#include "libav_deps.h"
#include "socket_pair.h"
#include "scoped_lock.h"
#include "libav_utils.h"
#include "logger.h"
#include <cstring>
#include <stdexcept>
#include <unistd.h>
......@@ -49,11 +52,10 @@ int ff_network_wait_fd(int fd)
struct pollfd p = { fd, POLLOUT, 0 };
int ret;
ret = poll(&p, 1, 100);
return ret < 0 ? errno : p.revents & (POLLOUT | POLLERR | POLLHUP) ? 0 : AVERROR(EAGAIN);
return ret < 0 ? errno : p.revents & (POLLOUT | POLLERR | POLLHUP) ? 0 : -EAGAIN;
}
struct addrinfo*
udp_resolve_host(const char *node, int service)
struct addrinfo* udp_resolve_host(const char *node, int service)
{
struct addrinfo hints, *res = 0;
int error;
......@@ -73,8 +75,7 @@ udp_resolve_host(const char *node, int service)
return res;
}
unsigned
udp_set_url(struct sockaddr_storage *addr,
unsigned udp_set_url(struct sockaddr_storage *addr,
const char *hostname, int port)
{
struct addrinfo *res0;
......@@ -89,8 +90,7 @@ udp_set_url(struct sockaddr_storage *addr,
return addr_len;
}
int
udp_socket_create(sockaddr_storage *addr, socklen_t *addr_len,
int udp_socket_create(sockaddr_storage *addr, socklen_t *addr_len,
int local_port)
{
int udp_fd = -1;
......@@ -174,10 +174,10 @@ void SocketPair::openSockets(const char *uri, int local_rtp_port)
{
char hostname[256];
char path[1024];
int rtp_port;
av_url_split(NULL, 0, NULL, 0, hostname, sizeof(hostname), &rtp_port,
path, sizeof(path), uri);
libav_utils::sfl_url_split(uri, hostname, sizeof(hostname), &rtp_port, path,
sizeof(path));
const int rtcp_port = rtp_port + 1;
......@@ -211,8 +211,7 @@ VideoIOHandle* SocketPair::getIOContext()
reinterpret_cast<void*>(this));
}
int
SocketPair::readCallback(void *opaque, uint8_t *buf, int buf_size)
int SocketPair::readCallback(void *opaque, uint8_t *buf, int buf_size)
{
SocketPair *context = static_cast<SocketPair*>(opaque);
......@@ -224,7 +223,7 @@ SocketPair::readCallback(void *opaque, uint8_t *buf, int buf_size)
for(;;) {
if (context->interrupted_)
return AVERROR_EXIT;
return -EINTR;
/* build fdset to listen to RTP and RTCP packets */
n = poll(p, 2, 100);
......@@ -241,7 +240,7 @@ SocketPair::readCallback(void *opaque, uint8_t *buf, int buf_size)
if (len < 0) {
if (errno == EAGAIN or errno == EINTR)
continue;
return AVERROR(EIO);
return -EIO;
}
break;
}
......@@ -257,14 +256,14 @@ SocketPair::readCallback(void *opaque, uint8_t *buf, int buf_size)
if (len < 0) {
if (errno == EAGAIN or errno == EINTR)
continue;
return AVERROR(EIO);
return -EIO;
}
break;
}
} else if (n < 0) {
if (errno == EINTR)
continue;
return AVERROR(EIO);
return -EIO;
}
}
return len;
......@@ -281,8 +280,7 @@ enum RTCPType {
#define RTP_PT_IS_RTCP(x) (((x) >= RTCP_FIR && (x) <= RTCP_IJ) || \
((x) >= RTCP_SR && (x) <= RTCP_TOKEN))
int
SocketPair::writeCallback(void *opaque, uint8_t *buf, int buf_size)
int SocketPair::writeCallback(void *opaque, uint8_t *buf, int buf_size)
{
SocketPair *context = static_cast<SocketPair*>(opaque);
......
......@@ -55,6 +55,9 @@ namespace sfl_video {
static int readCallback(void *opaque, uint8_t *buf, int buf_size);
static int writeCallback(void *opaque, uint8_t *buf, int buf_size);
private:
NON_COPYABLE(SocketPair);
pthread_mutex_t rtcpWriteMutex_;
int rtpHandle_;
......@@ -64,9 +67,6 @@ namespace sfl_video {
sockaddr_storage rtcpDestAddr_;
socklen_t rtcpDestAddrLen_;
bool interrupted_;
private:
NON_COPYABLE(SocketPair);
};
}
......
/*
* Copyright (C) 2013 Savoir-Faire Linux Inc.
* Author: Guillaume Roguez <Guillaume.Roguez@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA.
*
* Additional permission under GNU GPL version 3 section 7:
*
* If you modify this program, or any covered work, by linking or
* combining it with the OpenSSL project's OpenSSL library (or a
* modified version of that library), containing parts covered by the
* terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc.
* grants you additional permission to convey the resulting work.
* Corresponding Source for a non-source form of such a combination
* shall include the source code for the parts of OpenSSL used as well
* as that of the covered work.
*/
#include "libav_deps.h"
#include "video_base.h"
namespace sfl_video {
VideoPacket::VideoPacket() : packet_(0)
{
packet_ = static_cast<AVPacket *>(av_malloc(sizeof(AVPacket)));
}
VideoPacket::~VideoPacket() { av_free_packet(packet_); }
VideoIOHandle::VideoIOHandle(ssize_t buffer_size,
bool writeable,
io_readcallback read_cb,
io_writecallback write_cb,
io_seekcallback seek_cb,
void *opaque) : ctx_(0), buf_(0)
{
buf_ = static_cast<unsigned char *>(av_malloc(buffer_size));
ctx_ = avio_alloc_context(buf_, buffer_size, writeable, opaque, read_cb,
write_cb, seek_cb);
//ctx_->max_packet_size = buffer_size;
}
VideoIOHandle::~VideoIOHandle() { av_free(ctx_); av_free(buf_); }
VideoCodec::VideoCodec() : options_(0) {}
void VideoCodec::setOption(const char *name, const char *value)
{
av_dict_set(&options_, name, value, 0);
}
VideoFrame::VideoFrame() : frame_(avcodec_alloc_frame()) {}
VideoFrame::~VideoFrame() { avcodec_free_frame(&frame_); }
void VideoFrame::setGeometry(int width, int height, int pix_fmt)
{
frame_->format = libav_utils::libav_pixel_format(pix_fmt);
frame_->width = width;
frame_->height = height;
}
void VideoFrame::setDestination(void *data)
{
avpicture_fill((AVPicture *) frame_, (uint8_t *) data,
(PixelFormat) frame_->format, frame_->width,
frame_->height);
}
size_t VideoFrame::getSize()
{
return avpicture_get_size((PixelFormat) frame_->format,
frame_->width,
frame_->height);
}
}
......@@ -29,105 +29,88 @@
* as that of the covered work.
*/
#ifndef _VIDEO_BASE_H_
#define _VIDEO_BASE_H_
#ifndef _VIDEO_FRAME_H_
#define _VIDEO_FRAME_H_
#include "noncopyable.h"
extern "C" {
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
}
/* LIBAVFORMAT_VERSION_CHECK checks for the right version of libav and FFmpeg
* a is the major version
* b and c the minor and micro versions of libav
* d and e the minor and micro versions of FFmpeg */
#define LIBAVFORMAT_VERSION_CHECK( a, b, c, d, e ) \
( (LIBAVFORMAT_VERSION_MICRO < 100 && LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT( a, b, c ) ) || \
(LIBAVFORMAT_VERSION_MICRO >= 100 && LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT( a, d, e ) ) )
#include <cstdlib>
#include <cstdint>
#define HAVE_SDP_CUSTOM_IO LIBAVFORMAT_VERSION_CHECK(54,20,3,59,103)
typedef int(*io_readcallback)(void *opaque, uint8_t *buf, int buf_size);
typedef int(*io_writecallback)(void *opaque, uint8_t *buf, int buf_size);
typedef int64_t(*io_seekcallback)(void *opaque, int64_t offset, int whence);
class AVFrame;
class AVPacket;
class AVDictionary;
#ifndef AVFORMAT_AVIO_H
class AVIOContext;
#endif
enum VideoPixelFormat {
VIDEO_PIXFMT_BGRA = -1,
};
namespace sfl_video {
typedef int(*io_readcallback)(void *opaque, uint8_t *buf, int buf_size);
typedef int(*io_writecallback)(void *opaque, uint8_t *buf, int buf_size);
typedef int64_t(*io_seekcallback)(void *opaque, int64_t offset, int whence);
class VideoPacket {
public:
~VideoPacket() { av_free_packet(&inpacket_); };
AVPacket* get() const { return (AVPacket*)(&inpacket_); }
VideoPacket();
~VideoPacket();
AVPacket* get() { return packet_; };
private:
AVPacket inpacket_;
NON_COPYABLE(VideoPacket);
AVPacket *packet_;
};
class VideoIOHandle {
public:
VideoIOHandle(ssize_t buffer_size,
bool writeable,
io_readcallback read_cb,
io_writecallback write_cb,
io_seekcallback seek_cb,
void *opaque) : ctx_(0), buf_(0)
{
buf_ = static_cast<unsigned char *>(av_malloc(buffer_size));
ctx_ = avio_alloc_context(buf_, buffer_size, writeable, opaque, read_cb,
write_cb, seek_cb);
ctx_->max_packet_size = buffer_size;
}
VideoIOHandle(ssize_t buffer_size,
bool writeable,
io_readcallback read_cb,
io_writecallback write_cb,
io_seekcallback seek_cb,
void *opaque);
~VideoIOHandle();
~VideoIOHandle() { av_free(ctx_); av_free(buf_); }
AVIOContext *get() { return ctx_; }
AVIOContext* get() { return ctx_; }
private:
NON_COPYABLE(VideoIOHandle);
AVIOContext *ctx_;
unsigned char *buf_;
};
class VideoFrame {
class VideoCodec {
public:
VideoFrame() : frame_(avcodec_alloc_frame()) {}
~VideoFrame() { avcodec_free_frame(&frame_); };
VideoCodec();
virtual ~VideoCodec() {};
AVFrame *get() { return frame_; }
void setOption(const char *name, const char *value);
private:
NON_COPYABLE(VideoFrame);
NON_COPYABLE(VideoCodec);
AVFrame *frame_;
protected:
AVDictionary *options_;
};
class VideoCodec {
class VideoFrame {
public:
VideoCodec() : options_(0) {};
virtual ~VideoCodec() {};
VideoFrame();
~VideoFrame();
static size_t getBufferSize(PixelFormat pix_fmt, int width, int height)
{
return avpicture_get_size(pix_fmt, width, height);
}
void setOption(const char *name, const char *value)
{
av_dict_set(&options_, name, value, 0);
}
AVFrame* get() { return frame_; };
void setGeometry(int width, int height, int pix_fmt);
void setDestination(void *data);
size_t getSize();
private:
NON_COPYABLE(VideoCodec);
protected:
AVDictionary *options_;
NON_COPYABLE(VideoFrame);
AVFrame *frame_;
};
}
......
......@@ -29,23 +29,12 @@
* as that of the covered work.
*/
#include "libav_deps.h"
#include "video_decoder.h"
#include "check.h"
#include <iostream>
// libav includes
extern "C" {
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavdevice/avdevice.h>
#include <libswscale/swscale.h>
}
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(54, 28, 0)
// fallback to av_freep for older libavcodec
#define avcodec_free_frame av_freep
#endif
namespace sfl_video {
......@@ -59,9 +48,6 @@ VideoDecoder::VideoDecoder() :
lockedFrameCnt_(0),
lastFrame_(-1),
inputCtx_(avformat_alloc_context()),
imgConvertCtx_(0),
interruptCb_(),