Skip to content

Commit

Permalink
video encoding
Browse files Browse the repository at this point in the history
- user has to request ffmpeg support
- handle old version of ffmpeg
  • Loading branch information
LiangliangNan committed Nov 18, 2022
1 parent 9291d8b commit eb7d60d
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 16 deletions.
36 changes: 26 additions & 10 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@ option(Easy3D_BUILD_TESTS "Build Easy3D Tests" OFF)
option(Easy3D_ENABLE_CGAL "Build advanced features that require CGAL (>= v5.1)" OFF)
# Build advanced examples/applications that require Qt5 (>= v5.6)
option(Easy3D_ENABLE_QT "Build advanced examples/applications that require Qt5 (>= v5.6)" OFF)
# Build the video encoding module that requires ffmpeg
option(Easy3D_ENABLE_FFMPEG "Build the video encoding module that requires ffmpeg" OFF)

################################################################################

Expand Down Expand Up @@ -158,16 +160,29 @@ if (Easy3D_ENABLE_CGAL)
endif ()
endif ()

include(./cmake/FindFFMPEG.cmake)
if (FFMPEG_FOUND)
set(Easy3D_HAS_FFMPEG TRUE)
else ()
set(Easy3D_HAS_FFMPEG FALSE)
message(WARNING "You have requested FFMPEG support but FFMPEG was not found. "
"To use FFMPEG, make sure FFMPEG exists on your system (install/build FFMPEG if necessary). "
"You can modify the search paths of 'include' and 'lib' in 'Easy3D/cmake/FindFFMPEG.cmake', "
"and then run CMake. The FFMPEG support allows recording animation into a video file. "
"Ignore this message if you don't need this feature.")
if (Easy3D_ENABLE_FFMPEG)
include(./cmake/FindFFMPEG.cmake)
if (FFMPEG_FOUND)
set(Easy3D_HAS_FFMPEG TRUE)
else ()
set(Easy3D_HAS_FFMPEG FALSE)
message(WARNING "You have requested ffmpeg support but ffmpeg was not found (v4.0 or later required). "
"The ffmpeg support allows encoding/recording animation into a video file. You can ignore "
"this warning if you don't need this feature. \n"
"To enable video encoding, make sure ffmpeg exists on your system. Modify the search paths of "
"'include' and 'lib' in 'Easy3D/cmake/FindFFMPEG.cmake', and then run CMake. \n"
"How to install ffmpeg (v4.0 or later required)? \n"
" On Windows, you can download ffmpeg from: \n"
" https://ffmpeg.org/download.html \n"
" On macOS, use the following command to install ffmpeg: \n"
" brew install ffmpeg \n"
" On Linux, one has to install the libraries using: \n"
" sudo apt-get install libavcodec-dev \n"
" sudo apt-get install libavformat-dev \n"
" sudo apt-get install libswscale-dev \n"
" sudo apt-get install libavutil-dev \n"
)
endif ()
endif ()

################################################################################
Expand Down Expand Up @@ -313,6 +328,7 @@ message(STATUS " Build documentation : ${Easy3D_BUILD_DOCUMENTATION}")
message(STATUS " Build tests : ${Easy3D_BUILD_TESTS}")
message(STATUS " With CGAL (>= v5.1) : ${Easy3D_ENABLE_CGAL}")
message(STATUS " With Qt5 (>= v5.6) : ${Easy3D_ENABLE_QT}")
message(STATUS " With ffmpeg (>= v4.0) : ${Easy3D_ENABLE_FFMPEG}")
message(STATUS " Installation directory : ${CMAKE_INSTALL_PREFIX}")

message(STATUS "************************************************************")
Expand Down
7 changes: 5 additions & 2 deletions applications/Mapple/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,13 @@ class Mapple : public QApplication
try {
return QApplication::notify(receiver, event);
} catch(QException& e) {
LOG(ERROR) << "an exception was thrown: " << e.what();
LOG(ERROR) << "caught an exception: " << e.what();
}
catch(std::exception& e) {
LOG(ERROR) << "caught an exception: " << e.what();
}
catch(...) {
LOG(ERROR) << "an unknown exception was thrown";
LOG(ERROR) << "caught an unknown exception";
}
return false;
}
Expand Down
3 changes: 3 additions & 0 deletions applications/Mapple/paint_canvas_snapshot.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,10 @@ void PaintCanvas::recordAnimation(const QString &file_name, int fps, int bit_rat
const int fh = h * dpi_scaling();
VideoEncoder encoder;
if (!encoder.start(file_name.toStdString(), fps, bitrate)) {
// clean up and restore the settings before exit
encoder.end();
setEnabled(true);
easy3d::connect(&camera_->frame_modified, this, static_cast<void (PaintCanvas::*)(void)>(&PaintCanvas::update));
return;
}

Expand Down
2 changes: 1 addition & 1 deletion easy3d/video/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,5 @@ set(${module}_sources

add_module(${module} "${${module}_headers}" "${${module}_sources}" "${private_dependencies}" "${public_dependencies}")
target_include_directories(easy3d_${module} PRIVATE ${FFMPEG_INCLUDE_DIRS})
target_compile_definitions(easy3d_${module} PUBLIC HAS_CGAL)
target_compile_definitions(easy3d_${module} PUBLIC HAS_FFMPEG)
install_module(${module})
26 changes: 23 additions & 3 deletions easy3d/video/video_encoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
********************************************************************/

#include "video_encoder.h"
#include <easy3d/video/video_encoder.h>

extern "C" {
#include <libavcodec/avcodec.h>
Expand All @@ -35,6 +35,13 @@ extern "C" {

#include <easy3d/util/logging.h>


// check avcodec version
#if (LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 18, 100)) // this number corresponds to ffmpeg v4.0
#pragma message "[WARNING]: Your ffmpeg is too old. Please update it to v4.0 or above"
#endif


namespace internal {

// a wrapper around a single output AVStream
Expand Down Expand Up @@ -287,8 +294,10 @@ namespace internal {
LOG(WARNING) << "could not deduce output format from file extension: using MPEG";
avformat_alloc_output_context2(&fmt_ctx, nullptr, "mpeg", filename_.c_str());
}
if (!fmt_ctx)
return false;
if (!fmt_ctx) {
LOG(ERROR) << "failed to allocate the output media context";
return false;
}

fmt = fmt_ctx->oformat;
return true;
Expand Down Expand Up @@ -373,6 +382,9 @@ namespace internal {


void VideoEncoderImpl::end() {
if (!fmt_ctx) // video context was not created or has already been deleted
return;

av_write_trailer(fmt_ctx);

/* Close each codec. */
Expand All @@ -384,6 +396,7 @@ namespace internal {

/* free the stream */
avformat_free_context(fmt_ctx);
fmt_ctx = nullptr;
}

}
Expand All @@ -394,6 +407,13 @@ using namespace internal;
namespace easy3d {

VideoEncoder::VideoEncoder() : encoder_(nullptr) {
LOG(INFO) << "ffmpeg version : " << av_version_info();
LOG(INFO) << "avcodec_version: "
<< AV_VERSION_MAJOR(LIBAVCODEC_VERSION_INT) << "."
<< AV_VERSION_MINOR(LIBAVCODEC_VERSION_INT);
if (LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 18, 100)) // this number corresponds to ffmpeg v4.0
LOG(WARNING) << "your program was built with too old ffmpeg (" << av_version_info() << "), and "
<< "video encoding is not available. Contact the author of the program to fix it";
#ifdef NDEBUG
av_log_set_level(AV_LOG_QUIET);
#else
Expand Down

0 comments on commit eb7d60d

Please sign in to comment.