Commit 70cf3765 authored by François Grisez's avatar François Grisez
Browse files

Merge branch 'feature/videotoolbox_h265'

parents 222e1f6b 46144630
Pipeline #336 failed with stage
in 0 seconds
......@@ -107,6 +107,7 @@ cmake_dependent_option(ENABLE_VPX "Build mediastreamer2 with VPX codec." YES "EN
option(ENABLE_MKV "Enable support of MKV files reading and writing." YES)
cmake_dependent_option(ENABLE_QNX "Build medistreamer2 with BB10 filters." NO "ENABLE_VIDEO" NO)
cmake_dependent_option(ENABLE_VT_H264 "Build mediastreamer2 with H264 encoder/decoder based on VirtualToolbox (Apple only)" YES "ENABLE_VIDEO" NO)
cmake_dependent_option(ENABLE_VT_H265 "Build mediastreamer2 with H265 encoder/decoder based on VirtualToolbox (Apple only)" YES "ENABLE_VIDEO" NO)
option(ENABLE_JPEG "Enable JPEG support" YES)
option(ENABLE_QRCODE "Enable QRCode support" YES)
......@@ -539,7 +540,7 @@ if(APPLE)
list(APPEND LINK_FLAGS "-framework Foundation" "-framework QuartzCore" "-framework OpenGLES" "-framework UIKit" "-framework AVFoundation")
if(ENABLE_VIDEO)
list(APPEND LINK_FLAGS "-framework CoreGraphics" "-framework CoreMedia" "-framework CoreVideo")
if(ENABLE_VT_H264) # Necessary on iOS for Mediastreamer's tools and testers
if(ENABLE_VT_H264 OR ENABLE_VT_H265) # Necessary on iOS for Mediastreamer's tools and testers
list(APPEND LINK_FLAGS "-framework VideoToolbox")
endif()
endif()
......@@ -550,7 +551,7 @@ if(APPLE)
endif()
if(ENABLE_VIDEO)
list(APPEND LINK_FLAGS "-framework Cocoa" "-framework OpenGL" "-framework QuartzCore" "-framework AVFoundation")
if(ENABLE_VT_H264)
if(ENABLE_VT_H264 OR ENABLE_VT_H265)
list(APPEND LINK_FLAGS "-framework VideoToolbox -framework CoreMedia")
endif()
endif()
......
mediastreamer2 (Unreleased):
* H265 codec based of MediaCodec API (Android only)
* H265 codec based on MediaCodec API (Android only)
* H265 codec based on VideoToolbox API (iOS only)
mediastreamer2-2.16.1: July 21th, 2017
* Build fix for Windows
......
......@@ -168,6 +168,8 @@ typedef enum MSFilterId{
MS_AUDIO_FLOW_CONTROL_ID,
MS_MEDIACODEC_H265_DEC_ID,
MS_MEDIACODEC_H265_ENC_ID,
MS_VT_H265_DEC_ID,
MS_VT_H265_ENC_ID
} MSFilterId;
#endif
......@@ -836,6 +836,7 @@ struct _VideoStream
MSWebCam *cam;
RtpSession *rtp_io_session; /**< The RTP session used for RTP input/output. */
char *preset;
MSVideoConfiguration *vconf_list;
int device_orientation; /* warning: meaning of this variable depends on the platform (Android, iOS, ...) */
uint64_t last_reported_decoding_error_time;
uint64_t last_fps_check;
......
......@@ -285,6 +285,8 @@ typedef enum _MSRecorderState MSRecorderState;
MS_FILTER_METHOD(MSFilterVideoEncoderInterface, 9, const MSVideoConfiguration *)
#define MS_VIDEO_ENCODER_IS_HARDWARE_ACCELERATED \
MS_FILTER_METHOD(MSFilterVideoEncoderInterface, 10, bool_t)
#define MS_VIDEO_ENCODER_GET_CONFIGURATION \
MS_FILTER_METHOD(MSFilterVideoEncoderInterface, 11, MSVideoConfiguration )
/** Interface definitions for audio capture */
/* Start numbering from the end for hacks */
......
......@@ -204,6 +204,8 @@ set(VOIP_SOURCE_FILES_C
voip/stun.c
)
set(VOIP_SOURCE_FILES_CXX
utils/filter-wrapper/decoding-filter-wrapper.cpp
utils/filter-wrapper/encoding-filter-wrapper.cpp
)
set(VOIP_SOURCE_FILES_OBJC )
set(VOIP_SOURCE_FILES_ASM )
......@@ -301,18 +303,6 @@ if(ENABLE_VIDEO)
voip/videostarter.c
voip/videostream.c
)
list(APPEND VOIP_SOURCE_FILES_CXX
voip/h26x/h264-utils.cpp
voip/h26x/h265-utils.cpp
voip/h26x/h264-nal-packer.cpp
voip/h26x/h264-nal-unpacker.cpp
voip/h26x/h265-nal-packer.cpp
voip/h26x/h265-nal-unpacker.cpp
voip/h26x/h26x-utils.cpp
voip/h26x/nal-packer.cpp
voip/h26x/nal-unpacker.cpp
voip/h26x/rfc3984.cpp
)
if(FFMPEG_FOUND AND NOT TURBOJPEG_FOUND)
list(APPEND VOIP_SOURCE_FILES_C
videofilters/ffmpegnowebcam.c
......@@ -363,9 +353,6 @@ if(ENABLE_VIDEO)
)
endif()
endif()
if(APPLE)
list(APPEND VOIP_SOURCE_FILES_C videofilters/videotoolbox.c)
endif()
if(ANDROID)
list(APPEND VOIP_SOURCE_FILES_C
android/android-display.c
......@@ -378,14 +365,6 @@ if(ENABLE_VIDEO)
utils/shader_util.h
voip/scaler.c
)
list(APPEND VOIP_SOURCE_FILES_CXX
voip/h26x/media-codec-decoder.cpp
voip/h26x/media-codec-encoder.cpp
voip/h26x/media-codec-h264-decoder.cpp
voip/h26x/media-codec-h264-encoder.cpp
voip/h26x/media-codec-h265-decoder.cpp
voip/h26x/media-codec-h265-encoder.cpp
)
if(CMAKE_SYSTEM_PROCESSOR STREQUAL "armv7-a")
list(APPEND VOIP_SOURCE_FILES_ASM
voip/scaler_arm.S
......@@ -526,11 +505,22 @@ if(APPLE OR ANDROID OR OPENGL_FOUND OR GLX_FOUND OR QTANGLE_FOUND)
)
endif()
if (ENABLE_VT_H264 OR ENALBLE_VT_H265 OR ANDROID)
add_subdirectory(voip/h26x)
endif()
bc_apply_compile_flags(VOIP_SOURCE_FILES_C STRICT_OPTIONS_CPP STRICT_OPTIONS_C)
bc_apply_compile_flags(VOIP_SOURCE_FILES_OBJC STRICT_OPTIONS_CPP STRICT_OPTIONS_OBJC)
if(VOIP_SOURCE_FILES_CXX)
set_source_files_properties(${VOIP_SOURCE_FILES_CXX} PROPERTIES LANGUAGE CXX)
bc_apply_compile_flags(VOIP_SOURCE_FILES_CXX STRICT_OPTIONS_CPP STRICT_OPTIONS_CXX)
if (APPLE AND ENABLE_VT_H265 AND (CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64"))
set_source_files_properties(
voip/h26x/videotoolbox-utils.cpp
voip/h26x/videotoolbox.cpp
PROPERTIES COMPILE_DEFINITIONS "ENABLE_H265"
)
endif()
endif()
......
......@@ -433,6 +433,7 @@ void AMediaCodec_setParams(AMediaCodec *codec, const AMediaFormat * fmt) {
putToBundle(env, codec, jbundle, (AMediaFormat *)fmt, "request-sync");
putToBundle(env, codec, jbundle, (AMediaFormat *)fmt, "video-bitrate");
putToBundle(env, codec, jbundle, (AMediaFormat *)fmt, "frame-rate");
env->CallVoidMethod(codec->jcodec, codec->setParameters, jbundle);
handle_java_exception();
......
......@@ -32,6 +32,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "mediastreamer2/msfilter.h"
#include "mediastreamer2/mseventqueue.h"
#include "mediastreamer2/msvideo.h"
#include "mediastreamer2/mswebcam.h"
#include "basedescs.h"
......@@ -70,7 +71,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include <sys/syspage.h>
#endif
MS2_DEPRECATED static MSFactory *fallback_factory=NULL;
static void ms_fmt_descriptor_destroy(MSFmtDescriptor *obj);
......@@ -251,6 +251,22 @@ void ms_factory_register_filter(MSFactory* factory, MSFilterDesc* desc ) {
if (desc->id==MS_FILTER_NOT_SET_ID){
ms_fatal("MSFilterId for %s not set !",desc->name);
}
if (ms_filter_desc_implements_interface(desc, MSFilterVideoEncoderInterface)) {
MSFilterMethod *methods=desc->methods;
int i;
for(i=0;methods!=NULL && methods[i].method!=NULL; i++) {
if (methods[i].id==MS_FILTER_GET_BITRATE || methods[i].id==MS_FILTER_SET_BITRATE
|| methods[i].id==MS_FILTER_GET_VIDEO_SIZE || methods[i].id==MS_FILTER_SET_VIDEO_SIZE
|| methods[i].id==MS_FILTER_GET_FPS || methods[i].id==MS_FILTER_SET_FPS
|| methods[i].id==MS_VIDEO_ENCODER_SET_CONFIGURATION_LIST
) {
ms_error("MSFilter %s is using a deprecated method (id=%i)",desc->name,methods[i].id);
return;
}
}
}
desc->flags|=MS_FILTER_IS_ENABLED; /*by default a registered filter is enabled*/
/*lastly registered encoder/decoders may replace older ones*/
......
/*
* Mediastreamer2 decoder-filter.h
* Copyright (C) 2018 Belledonne Communications SARL
*
* 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 2
* 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.
*/
#pragma once
#include "mediastreamer2/msvideo.h"
#include "filter-base.h"
namespace mediastreamer {
class DecoderFilter: public FilterBase {
public:
DecoderFilter(MSFilter *f): FilterBase(f) {}
virtual MSVideoSize getVideoSize() const = 0;
virtual float getFps() const = 0;
virtual const MSFmtDescriptor *getOutputFmt() const = 0;
virtual void addFmtp(const char *fmtp) = 0;
virtual void enableAvpf(bool enable) = 0;
virtual bool freezeOnErrorEnabled() const = 0;
virtual void enableFreezeOnError(bool enable) = 0;
virtual void resetFirstImage() = 0;
};
} // namespace mediastreamer
/*
* Mediastreamer2 encoder-filter.h
* Copyright (C) 2018 Belledonne Communications SARL
*
* 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 2
* 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.
*/
#pragma once
#include "mediastreamer2/msvideo.h"
#include "filter-base.h"
namespace mediastreamer {
class EncoderFilter: public FilterBase {
public:
EncoderFilter(MSFilter *f): FilterBase(f) {}
virtual const MSVideoConfiguration *getVideoConfigurations() const = 0;
virtual const MSVideoConfiguration &getVideoConfiguration() const = 0;
virtual void setVideoConfiguration(MSVideoConfiguration vconf) = 0;
virtual void enableAvpf(bool enable) = 0;
virtual void requestVfu() = 0;
virtual void notifyPli() = 0;
virtual void notifyFir() = 0;
virtual void notifySli() = 0;
};
} // namespace mediastreamer
/*
Mediastreamer2 filter-base.h
Copyright (C) 2018 Belledonne Communications SARL
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 2
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.
*/
#pragma once
#include <exception>
#include "mediastreamer2/msfilter.h"
#include "mediastreamer2/msticker.h"
namespace mediastreamer {
class FilterBase {
public:
class MethodCallFailed: public std::exception {};
FilterBase(MSFilter *f): _f(f) {}
virtual ~FilterBase() = default;
virtual void preprocess() = 0;
virtual void process() = 0;
virtual void postprocess() = 0;
protected:
MSFactory *getFactory() const {return _f->factory;}
MSQueue *getInput(int idx) const {return _f->inputs[idx];}
MSQueue *getOutput(int idx) const {return _f->outputs[idx];}
uint64_t getTime() const {return _f->ticker->time;}
void notify(unsigned int id) {ms_filter_notify_no_arg(_f, id);}
void lock() const {ms_filter_lock(_f);}
void unlock() const {ms_filter_unlock(_f);}
private:
MSFilter *_f = nullptr;
};
} // namespace mediastreamer
/*
Mediastreamer2 decoding-filter-wrapper.cpp
Copyright (C) 2018 Belledonne Communications SARL
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 2
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.
*/
#include "decoding-filter-wrapper.h"
using namespace std;
namespace mediastreamer {
int DecodingFilterWrapper::onAddFmtpCall(MSFilter *f, void *arg) {
try {
const char *fmtp = static_cast<const char *>(arg);
static_cast<DecoderFilter *>(f->data)->addFmtp(fmtp);
return 0;
} catch (const DecoderFilter::MethodCallFailed &) {
return -1;
}
}
int DecodingFilterWrapper::onResetFirstImageCall(MSFilter *f, void *arg) {
try {
static_cast<DecoderFilter *>(f->data)->resetFirstImage();
return 0;
} catch (const DecoderFilter::MethodCallFailed &) {
return -1;
}
}
int DecodingFilterWrapper::onGetVideoSizeCall(MSFilter *f, void *arg) {
try {
MSVideoSize *vsize = static_cast<MSVideoSize *>(arg);
*vsize = static_cast<DecoderFilter *>(f->data)->getVideoSize();
return 0;
} catch (const DecoderFilter::MethodCallFailed &) {
return -1;
}
}
int DecodingFilterWrapper::onGetFpsCall(MSFilter *f, void *arg) {
try {
float *fps = static_cast<float *>(arg);
*fps = static_cast<DecoderFilter *>(f->data)->getFps();
return 0;
} catch (const DecoderFilter::MethodCallFailed &) {
return -1;
}
}
int DecodingFilterWrapper::onGetOutFmtCall(MSFilter *f, void *arg) {
try {
MSPinFormat *pinFormat = static_cast<MSPinFormat *>(arg);
pinFormat->fmt = static_cast<DecoderFilter *>(f->data)->getOutputFmt();
return 0;
} catch (const DecoderFilter::MethodCallFailed &) {
return -1;
}
}
int DecodingFilterWrapper::onEnableAvpfCall(MSFilter *f, void *arg) {
try {
const bool_t *enable = static_cast<bool_t *>(arg);
static_cast<DecoderFilter *>(f->data)->enableAvpf(*enable);
return 0;
} catch (const DecoderFilter::MethodCallFailed &) {
return -1;
}
}
int DecodingFilterWrapper::onEnableFreezeOnErrorCall(MSFilter *f, void *arg) {
try {
const bool_t *enable = static_cast<bool_t *>(arg);
static_cast<DecoderFilter *>(f->data)->enableFreezeOnError(*enable);
return 0;
} catch (const DecoderFilter::MethodCallFailed &) {
return -1;
}
}
int DecodingFilterWrapper::onFreezeOnErrorEnabledCall(MSFilter *f, void *arg) {
try {
bool_t *foeEnabled = static_cast<bool_t *>(arg);
*foeEnabled = static_cast<DecoderFilter *>(f->data)->freezeOnErrorEnabled();
return 0;
} catch (const DecoderFilter::MethodCallFailed &) {
return -1;
}
}
}
/*
Mediastreamer2 decoding-filter-wrapper.h
Copyright (C) 2018 Belledonne Communications SARL
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 2
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.
*/
#pragma once
#include "mediastreamer2/msfilter.h"
#include "filter-interface/decoder-filter.h"
#include "filter-wrapper-base.h"
namespace mediastreamer {
class DecodingFilterWrapper {
public:
static int onAddFmtpCall(MSFilter *f, void *arg);
static int onResetFirstImageCall(MSFilter *f, void *arg);
static int onGetVideoSizeCall(MSFilter *f, void *arg);
static int onGetFpsCall(MSFilter *f, void *arg);
static int onGetOutFmtCall(MSFilter *f, void *arg);
static int onEnableAvpfCall(MSFilter *f, void *arg);
static int onEnableFreezeOnErrorCall(MSFilter *f, void *arg);
static int onFreezeOnErrorEnabledCall(MSFilter *f, void *arg);
};
}
#define MS_DECODING_FILTER_WRAPPER_METHODS_DECLARATION(base_name) \
static MSFilterMethod MS_FILTER_WRAPPER_METHODS_NAME(base_name)[] = { \
{ MS_FILTER_ADD_FMTP , DecodingFilterWrapper::onAddFmtpCall }, \
{ MS_VIDEO_DECODER_RESET_FIRST_IMAGE_NOTIFICATION , DecodingFilterWrapper::onResetFirstImageCall }, \
{ MS_FILTER_GET_VIDEO_SIZE , DecodingFilterWrapper::onGetVideoSizeCall }, \
{ MS_FILTER_GET_FPS , DecodingFilterWrapper::onGetFpsCall }, \
{ MS_FILTER_GET_OUTPUT_FMT , DecodingFilterWrapper::onGetOutFmtCall }, \
{ MS_VIDEO_DECODER_ENABLE_AVPF , DecodingFilterWrapper::onEnableAvpfCall }, \
{ MS_VIDEO_DECODER_FREEZE_ON_ERROR , DecodingFilterWrapper::onEnableFreezeOnErrorCall }, \
{ MS_VIDEO_DECODER_FREEZE_ON_ERROR_ENABLED , DecodingFilterWrapper::onFreezeOnErrorEnabledCall }, \
{ 0 , nullptr } \
}
#define MS_DECODING_FILTER_WRAPPER_DESCRIPTION_DECLARATION(base_name, id, text, enc_fmt, flags) \
MS_FILTER_WRAPPER_FILTER_DESCRIPTION_BASE(base_name, id, text, MS_FILTER_DECODER, enc_fmt, 1, 1, flags)
/*
Mediastreamer2 encoding-filter-wrapper.cpp
Copyright (C) 2018 Belledonne Communications SARL
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 2
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.
*/
#include "encoding-filter-wrapper.h"
using namespace std;
namespace mediastreamer {
int EncodingFilterWrapper::onGetVideoConfigurationsCall(MSFilter *f, void *arg) {
try {
const MSVideoConfiguration **vconfs = static_cast<const MSVideoConfiguration **>(arg);
*vconfs = static_cast<EncoderFilter *>(f->data)->getVideoConfigurations();
return 0;
} catch (const EncoderFilter::MethodCallFailed &) {
return -1;
}
}
int EncodingFilterWrapper::onGetConfigurationCall(MSFilter *f, void *arg) {
try {
MSVideoConfiguration *vconf = static_cast<MSVideoConfiguration *>(arg);
*vconf = static_cast<const EncoderFilter *>(f->data)->getVideoConfiguration();
return 0;
} catch (const EncoderFilter::MethodCallFailed &) {
return -1;
}
}
int EncodingFilterWrapper::onSetConfigurationCall(MSFilter *f, void *arg) {
try {
const MSVideoConfiguration *vconf = static_cast<MSVideoConfiguration *>(arg);
static_cast<EncoderFilter *>(f->data)->setVideoConfiguration(*vconf);
return 0;
} catch (const EncoderFilter::MethodCallFailed &) {
return -1;
}
}
int EncodingFilterWrapper::onEnableAvpfCall(MSFilter *f, void *arg) {
try {
const bool_t *enable = static_cast<bool_t *>(arg);
static_cast<EncoderFilter *>(f->data)->enableAvpf(*enable);
return 0;
} catch (const EncoderFilter::MethodCallFailed &) {
return -1;
}
}
int EncodingFilterWrapper::onRequestVfuCall(MSFilter *f, void *arg) {
try {
static_cast<EncoderFilter *>(f->data)->requestVfu();
return 0;
} catch (const EncoderFilter::MethodCallFailed &) {
return -1;
}
}
int EncodingFilterWrapper::onNotifyPliCall(MSFilter *f, void *arg) {
try {
static_cast<EncoderFilter *>(f->data)->notifyPli();
return 0;
} catch (const EncoderFilter::MethodCallFailed &) {
return -1;
}
}
int EncodingFilterWrapper::onNotifyFirCall(MSFilter *f, void *arg) {
try {
static_cast<EncoderFilter *>(f->data)->notifyFir();
return 0;
} catch (const EncoderFilter::MethodCallFailed &) {