Coder Social home page Coder Social logo

ffmpeg-cpp's Introduction

ffmpeg-cpp

A clean C++ wrapper around the ffmpeg libraries which can be used in any C++ project or C# project (with DllImport or CLR). Makes the most commonly used functionality of FFmpeg easily available for any C++ projects with an easy-to-use interface. The full power of FFmpeg compacted in 10 lines of C++ code: if this sounds useful to you, read on!

Installation

Windows

  1. Clone the repository
  2. Download a build of FFmpeg from https://ffmpeg.zeranoe.com/builds/. The project was last tested with 4.1. You will need both the dev version (for .h and .lib files) and the shared version (for .dll). Extract all of them into the ffmpeg directory in the repository. there are more instructions on how to extract them properly in the ffmpeg/readme.txt file.
  3. Open the Visual Studio solution in the source directory.
  4. Build everything.

This will build a .lib file that you can use in your own C++ projects. It will also generate an include-folder in the repo root that you can add to your include filders in your own project.

Linux

Currently, only a Windows environment with Visual Studio is supported. This is simply because I do not have experience with cmake and Linux-projects, since the project itself is fully platform-independent. If anyone is willing to help me out with configuring cmake, please get in touch!

Usage

There are multiple demo projects included in the solution. Check out the demo-project for a thorough exploration of the features (demuxing, decoding, filtering, encoding, muxing) or one of the other examples for a simpler example to follow.

There is also a .NET Core compatible simplified interface included so that you can embed this project in your .NET Core projects.

C++

To give you an idea, this code will load a video stream from a container, filter it, and write it back out to another container:

// Create a muxer that will output the video as MP4.
Muxer* muxer = new Muxer("filtered_video.mp4");

// Create a MPEG2 codec that will encode the raw data.
VideoCodec* codec = new VideoCodec(AV_CODEC_ID_MPEG2VIDEO);

// Create an encoder that will encode the raw audio data using the codec specified above.
// Tie it to the muxer so it will be written to file.
VideoEncoder* encoder = new VideoEncoder(codec, muxer);

// Create a video filter and do some funny stuff with the video data.
Filter* filter = new Filter("scale=640:150,transpose=cclock,vignette", encoder);

// Load a container. Pick the best video stream container in the container
// And send it to the filter.
Demuxer* demuxer = new Demuxer("big_buck_bunny.mp4");
demuxer->DecodeBestVideoStream(filter);

// Prepare the output pipeline.
// This will decode a small amount of frames so the pipeline can configure itself.
demuxer->PreparePipeline();

// Push all the remaining frames through.
while (!demuxer->IsDone())
{
	demuxer->Step();
}
		
// Save everything to disk by closing the muxer.
muxer->Close();

If you use the included simple-interface library, which only supports a subset of the full library, using ffmpeg-cpp becomes even easier:

#include "SimpleInterface.h"

int main()
{
	void* handle = ffmpegCppCreate("out.mp4");
	ffmpegCppAddVideoStream(handle, "samples/big_buck_bunny.mp4");
	ffmpegCppAddVideoFilter(handle, "transpose=cclock[middle];[middle]vignette");
	ffmpegCppAddAudioStream(handle, "samples/big_buck_bunny.mp4");
	ffmpegCppGenerate(handle);
	ffmpegCppClose(handle);
}

C#

The simple-interface is made in such a way that it can easily be called using [DllImport] from any C# project:

	public class Example
	{

		public Example()
		{
			try
			{
				string inFileName = "in.mp4";
				string outFileName = "out.mp4";
				IntPtr handle = ffmpegCppCreate(outFileName); CheckError(handle);
				ffmpegCppAddVideoStream(handle, inFileName); CheckError(handle);
				ffmpegCppAddAudioStream(handle, inFileName); CheckError(handle);
				ffmpegCppAddVideoFilter(handle, "crop=1080:1920:740:0[middle];[middle]transpose=3"); CheckError(handle);
				ffmpegCppGenerate(handle); CheckError(handle);
				ffmpegCppClose(handle);
			}
			catch (InvalidOperationException e)
			{
				Console.WriteLine("ERROR: " + e.Message);
			}
		}

		private void CheckError(IntPtr handle)
		{
			if (ffmpegCppIsError(handle))
			{
				IntPtr errorPtr = ffmpegCppGetError(handle);
				string error = Marshal.PtrToStringAnsi(errorPtr);
				throw new InvalidOperationException(error);
			}
		}

		[DllImport("simple_interface.dll", CallingConvention = CallingConvention.Cdecl)]
		private static extern IntPtr ffmpegCppCreate(string outFileName);

		[DllImport("simple_interface.dll", CallingConvention = CallingConvention.Cdecl)]
		private static extern void ffmpegCppAddVideoStream(IntPtr handle, [MarshalAs(UnmanagedType.LPStr)] string inFileName);

		[DllImport("simple_interface.dll", CallingConvention = CallingConvention.Cdecl)]
		private static extern void ffmpegCppAddAudioStream(IntPtr handle, [MarshalAs(UnmanagedType.LPStr)] string inFileName);

		[DllImport("simple_interface.dll", CallingConvention = CallingConvention.Cdecl)]
		private static extern void ffmpegCppAddVideoFilter(IntPtr handle, [MarshalAs(UnmanagedType.LPStr)] string filterString);

		[DllImport("simple_interface.dll", CallingConvention = CallingConvention.Cdecl)]
		private static extern void ffmpegCppAddAudioFilter(IntPtr handle, [MarshalAs(UnmanagedType.LPStr)] string filterString);

		[DllImport("simple_interface.dll", CallingConvention = CallingConvention.Cdecl)]
		private static extern void ffmpegCppGenerate(IntPtr handle);

		[DllImport("simple_interface.dll", CallingConvention = CallingConvention.Cdecl)]
		private static extern bool ffmpegCppIsError(IntPtr handle);

		[DllImport("simple_interface.dll", CallingConvention = CallingConvention.Cdecl)]
		private static extern IntPtr ffmpegCppGetError(IntPtr handle);

		[DllImport("simple_interface.dll", CallingConvention = CallingConvention.Cdecl)]
		private static extern void ffmpegCppClose(IntPtr handle);
	}

If you want to use ffmpeg-cpp in a C# project, you can easily do so by making your own C-wrapper around the

Why?

I developed this project to be able to to integrate FFmpeg into our program without having to call the executable to do an operation. This is important because starting up an external executable tends to be blocked by antivirus software and can cause issues with users. It has been tested for the most common functionality, and some of the examples from https://github.com/FFmpeg/FFmpeg/tree/master/doc/examples are mirrored in the project as well.

Roadmap

  • Add Linux/Mac build support
  • Adding proper unit tests
  • Testing with more codecs, containers

License

This library is licensed under LGPL (https://en.wikipedia.org/wiki/GNU_Lesser_General_Public_License).

Please note though that FFmpeg, which you will need to build this library, is not. Depending on how you build it, it is either LGPL or GPL. So if you use the GPL-version of FFmpeg in your project, this library will be GPL too.

ffmpeg-cpp's People

Contributors

leonyu1010 avatar raveler avatar ziriax avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ffmpeg-cpp's Issues

Building ffmpeg libraries for Qt

I want to use your wrapper in Qt, but the libraries are built with a MSVS compiler. so, the Qt compiler won't work with these. Now I've tried to build the project with Qt, but I've got a lot of errors on the ffmpeg header files.
So I was wondering if I just could compile the libraries with MinGW?

cannot support Alpha-Channel video?

I tested a video file with .webm format, and you can see its translucent effect in chrome. After decoding with ffmpeg-cpp, cv::Mat does have 4 channels, but the value of the alpha channel is all 255 , Is my operation incorrect?

cannot load nvcuda.dll

The build was successful, but when I've tried to run the demo.cpp it crashed.
in the demo.exe i've got following feedback:
Encoding video as H264 on Nvidia GPU... Applying filter transpose=cclock[middle];[middle]vignette to video... Pulling video from samples/carphone.h264... [h264_nvenc @ 000001f8d00602c0] Cannot load nvcuda.dll Could not open codecContext for codec: Operation not permitted
when going back to VS I see that the error got catched by the FFmpegException and output is the following:

'demo.exe' (Win32): Loaded 'C:\Windows\System32\cryptbase.dll'. Cannot find or open the PDB file.
The thread 0x1960 has exited with code 0 (0x0).
Exception thrown at 0x00007FFEB1B0A388 in demo.exe: Microsoft C++ exception: ffmpegcpp::FFmpegException at memory location 0x0000005F2E0FC420.
Exception thrown at 0x00007FFEB1B0A388 in demo.exe: Microsoft C++ exception: ffmpegcpp::FFmpegException at memory location 0x0000005F2E0FF750.
Unhandled exception at 0x00007FFEB1B0A388 in demo.exe: Microsoft C++ exception: ffmpegcpp::FFmpegException at memory location 0x0000005F2E0FF750.

The program '[15140] demo.exe' has exited with code 0 (0x0).

Reading timecode metadata from file?

Hi! And thanks for making this code available (the only windows build-able ffmpeg that I could find).

I am trying to read the metadata from a .mov file, specifically timecode data.

Based on the 'print_info' example, this code:

VideoStreamInfo stream = info.videoStreams[i];
			cout << "Stream #" << (i + 1)
				<< ": codec " << stream.codec->name
				<< ", pixel format " << stream.formatName
				<< ", resolution " << stream.width << "x" << stream.height
				<< ", bit rate " << stream.bitRate << "kb/s"
				<< ", fps " << ((float)stream.frameRate.num / (float)stream.frameRate.den)
				<< ", time base " << stream.timeBase.num  << "/" << stream.timeBase.den
		
				<< ", " << demuxer->GetFrameCount(stream.id) << " frames"
				<< endl;

prints as expected, how can I read the timecode from the file in the same way?

Thanks again!

Amerge filter

Hi,
Thank you very much for ffmpeg-cpp. Very useable.
Can you help me with amerge filter for merge two audio files?
My code:

Muxer* muxer = new Muxer("output.wav");
AudioCodec* codec = new AudioCodec(AV_CODEC_ID_ADPCM_IMA_WAV);
AudioEncoder* encoder = new AudioEncoder(codec, muxer);
Filter* filter = new Filter("amerge", encoder);

Demuxer* source1 = new Demuxer("audio1.wav");
source1->DecodeBestAudioStream(filter);

Demuxer* source2 = new Demuxer("audio2.wav");
source2->DecodeBestAudioStream(filter);

source1->PreparePipeline();
source2->PreparePipeline();

while (!source1->IsDone()) {
source1->Step();
source2->Step();
}
muxer->Close();

Output file consist only header.

Kind regards, Yevgeniy.

Setting packet duration

Hi, I'm learning to use FFmpeg and I have a question regarding this packet duration calculation:
pkt->duration = stream->time_base.den / stream->time_base.num / stream->avg_frame_rate.num * stream->avg_frame_rate.den;
https://github.com/Raveler/ffmpeg-cpp/blob/master/source/ffmpeg-cpp/ffmpeg-cpp/Muxing/VideoOutputStream.cpp#L82

I have also experienced the incorrect total duration/frame rate with h264/mp4, if packet duration is not set.

When encoding, I have just set packets' duration to 1 as they come out of the encoder (fair enough for CFR content) and then call av_packet_rescale_ts() to rescale it to the stream timebase.

Your calculation appears to be (1/Tb) * (1/Fr), where Tb is the stream timebase and Fr is the stream average framerate.
This will be constant for CFR streams, and equivalent to setting the duration to 1 before the rescale. So what is the benefit of doing this more complex calculation? If the stream is VFR isn't this duration pretty much always wrong? Isn't it kind of just a guess of the average frame duration so far/

Also, wouldn't it be better to use the AVRational math functions to do this calculation to prevent overflow and other potential issues.
e.g.:
pkt->duration = av_mul_q(av_inv_q(stream->time_base), av_inv_q(stream->avg_frame_rate));

I'd appreciate if you could offer any insight into this, and maybe explain why this line of code is the way it is.

Thank you!
-Nathan

compiling error

I do not know if it is the problem of of enviroment. I cannot compile the example project successfully.
It complains something like this,
libav-cpp/av/Decoder.hpp:81:26: error: ‘Packet’ has not been declared

It seems that the complier cannot find the header files under av/ directory. But I see it is right when checking
message("AV files: ${AV_FILES}")

What is wrong with it? I did not make any change from the git repo.

Is this library good for Real-time IP Camera Video capturing and recording?

First of all, Thank you so much for this awesome project!
Secondly can you please mention if this library is good for real-time IP Camera Video capturing and recording? If yes, can you please include an example project in samples showing how to use this repository to record a live stream? I mean a live video is usually an endless video so how we can configure this library to save the video continuously or after an interval?

A sample rtsp stream address:
rtsp://wowzaec2demo.streamlock.net/vod/mp4:BigBuckBunny_115k.mov

Best regards

UDP streaming

@Raveler
I want to stream OpenGL buffer data through UDP, I am a beginner in FFmpeg and would like to know if your projects could append frames from the OpenGL rendering to a stream and the same could be either played or saved per frame after decoding.

Thank you for publishing your wonderful project

For your information

@Raveler

Hello,

First over all, thanks a lot for sharing your code, ffmpeg-cpp is really a nice idea, and works already very well (including on Linux).

My purpose is to (at least I expect to) first understand and simply use your very nice API in another software (see https://framagit.org/ericb/miniDart ), as a part of the final software (big factorization and layout redesign in progress, but not yet published). And I'll very probably use your lib, for several reasons:

  • I'm impressed by the way filter are handled. This is really black magic (filters are the worst source code documentation ever in ffmpeg)
  • light (and fast !)
  • I'm not satified of OpenCV video recording, nor reliable and somewhere fully buggy, and difficult to use for recording.
  • your API seems extremely well designed (maybe some parts are missing, but easy to understand and use)
  • I'd like to remux sound from several sources (using SDL2 for the sources), and currently only ffmpeg, or lib555 are a correct answer for the final muxing.

Other change : I do not like Github (being tracked for everything by Microsoft and more, + some other reasons) I preferred fork your code somewhere else. See: https://framagit.org/ericb/ffmpeg-cpp2 .

If something is missing, please tell me, and I'll add the information.

Of course, feel free to ask if something could be reversed to your project. For example, I started to implement the recording from a webcam (mjpeg). Even if it is currently sub-optimal, it works well, and the only missing part is to display colored frames + record in a file (I'm exactly stuck there : how to record color channels btw ?).

Current WIP : understand more precisely the fileSink, inputstream and output handling.

Last but not least, and as I wrote in another issue, I completed the Linux build and everything seems to work. Currently, all the changes are under GPL V3 license, to protect my work, but that's not a problem for me to reverse some part under LGPL on demand (be carefull : I modified the tree, more easy on Linux). I forgot : miniDart is by default cross compiled on Linux, for Windows. I don"t use the last in the mood API, but I promise it works on Windows too.

demo with 'GENERATED video failed

While checking if this lib I noticed I had to remove this line below to get the demo project to work with 'GENERATED' video output
it resets the frame and caused the next WriteFrame call to fail with 'Invalid argument' trown.

Removing this call seems to work for the demo. However perhaps this could cause mem leaks elsewhere since it unreferences buffers also. Liking the lib so far though ty!

OpenCV and RTMP

Hi,
ffmpeg for cpp is quite challenging so thanks. I was wondering if this could be used as well using openCV Mat as input, and RTMP output

transcode to memory

Is there a way to set up a muxer recipient to be memory instead of file?

I need the transcoded and muxed output in a memory buffer rather than written to file.

Thanks

Andrea

support for latest ffmpeg version

hello,

this seems to a good library and learning point to understand ffmpeg.

when can we have the support for latest ffmpeg library.

thanks & regards,
Amit. K.

Win32 version

Not an issue, more of a suggestion....

Have you thought about supporting x86/Win32 build as well as x64?
Seems like it would just involve modifying the download script to pull both versions and then fiddling project properties to link the correct version.

Really handy project. Thank you for doing this.

filter output

Not an issue, but a request. Your library is very nice, elegant, thanks for providing! Background: I compiled FFmpeg 4.2.2 using msys2 / gcc7.3.0. I compiled ffmpeg-cpp into a DLL using Qt and gcc7.3.0. Examples I have compiled are working well. I am interested in audio filters. I have started with the filtering_audio example. How do I get the output of each filter? For example, loudnorm uses a 2-pass approach (see http://k.ylo.ph/2016/04/04/loudnorm.html), where you parse the output of the first pass, and use those parameters in the second. Would appreciate if you can provide guidance.

Linux support

Having trouble interfacing with the ffmpeg C API directly from C++, I would like to give a try to ffmpeg-cpp.
Unfortunately, it's not that straightforward.

First of all, the windows only crtdbg.h is included from ffmpeg.h (and the later have a common name which could cause troubles on Linux).
This can be fixed by adding the proper #ifdef statement.

But then, I got the following error :

../FFmpegException.h:18:23: error: looser exception specification on overriding virtual function ‘virtual const char* ffmpegcpp::FFmpegException::what() const’ 18 | virtual char const* what() const

I do think this is specific to Windows exception implementation.

If someone is interested in, the CMakelists is attached.
It should go to source/ffmpeg-cpp/ffmpeg-cpp folder.
This is a very kick of, only files besides the CMakelists.txt are taken (nothing from subdirectories).
CMakeLists.txt

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.