1. Foreword
From the beginning of this article, I will gradually go deep into the use of FFmpeg API, not just using ffmpeg command line, which is simple and powerful but has certain limitations. Using the command line, we can easily complete some of our specific work, but if we want to use ffmpeg to return the processing results to other users, or if ffmpeg needs to be embedded in our project, we must learn to use the API provided by ffmpeg to write code to complete the work.
Back to the main content of this article. First, before analyzing the video, we often need to know the video stream information contained in the media file, such as file format, playback time, video code rate, video frame rate, video codec format, audio code rate, audio sampling rate and so on. If you use the command line, you only need FFmpeg - I input Mp4 can obtain the above information. However, how to use the API provided by FFmpeg to obtain this information is the content of this article.
First, put a running result diagram. As can be seen from the figure, the information mentioned above has been obtained.
2. Code environment
I use the development environment of windows10 + qt creator, and the compilation environment is MSVC2017.
It should be noted that before using FFmpeg API to write code, add the FFmpeg to be used to the project of qt project. Station B has a video explaining how to configure the environment. The explanation is fairly clear and can be used as a reference. If you have any questions, please leave a message in the comment area and I will reply in time.
Station B qt creator+windows+ffmpeg configuration address: https://www.bilibili.com/video/BV1zN411d7st?p=4
3. Code
I encapsulate the work mentioned above into a class. If your environment is built, you can directly copy the code and run it. First run to see the effect, and then study the code carefully.
- Class header file code (videoinformation.h)
// Copyright (c) 2021 LucasNan <nanche@mail.hfut.edu.cn> <www.kevinnan.org.cn> // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation // files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the // Software is furnished to do so, subject to the following // conditions: // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR // OTHER DEALINGS IN THE SOFTWARE. #ifndef VIDEOINFORMATION_H #define VIDEOINFORMATION_H #include <iostream> #include <string> extern "C"{ #include "libavcodec/avcodec.h" #include "libavformat/avformat.h" } /* What information does the video have? * (1) population * - Format o * - Codec * - file size * - Duration o * - Overall rate mode * - Overall bit rate * - date * (2) For video * - ID o * - Format o * - Bit rate o * - Maximum Bitrate * - Width o * - Height o * - Frame rate mode * - Frame rate o * - Color space * - chroma subsampling * - Bit depth * - Stream size o * (3) For audio * - Format o * - Bit rate o * - Number of channels o * - Sampling rate o * - Compression mode * - Stream size o */ class VideoInformation { public: VideoInformation(); ~VideoInformation(){ avformat_close_input(&input_AVFormat_context_); } //@brief: get video information //@param: file_path: file path //@ret : void //@birth: created by LucasNan on 20210218 void getVideoInfo(std::string file_path); //@brief: get format //@param: void //@ret: video format //@birth: created by LucasNan on 20210219 std::string getFormat(){ return this->format_; } //@brief: get video length //@param: void //@ret: video length //@birth: created by LucasNan on 20210219 std::string getDuration(){ return this->duration_; } //@brief: get video frame rate //@param: void //@ret: video frame rate //@birth: created by LucasNan on 20210219 int getFrameRate(){ return this->frame_rate_; } //@brief: get the video bit rate //@param: void //@ret: average video bit rate //@birth: created by LucasNan on 20210219 int getVideoAverageBitRate(){ return this->video_average_bit_rate_; } //@brief: get video width //@param: void //@ret: video width //@birth: created by LucasNan on 20210219 int getWidth(){ return this->width_; } //@brief: get video height //@param: void //@ret: video height //@birth: created by LucasNan on 20210219 int getHeight(){ return this->height_; } //@brief: get the video stream size //@param: void //@ret: video stream size //@birth: created by LucasNan on 20210219 float getVideoSize(){ return this->video_size_; } //@brief: get the video coding format //@param: void //@ret: video coding format //@birth: created by LucasNan on 20210219 std::string getVideoFormat(){ return this->video_format_; } std::string getAudioFormat(){ return this->audio_format_; } //@brief: get the average audio bit rate //@param: void //@ret: average audio bit rate //@birth: created by LucasNan on 20210219 int getAudioAverageBitRate(){ return this->audio_average_bit_rate_; } //@brief: get the number of audio channels //@param: void //@ret: number of audio channels //@birth: created by LucasNan on 20210219 int getChannelNumbers(){ return this->channel_nums; } //@brief: get the audio sampling rate //@param: void //@ret: audio sampling rate //@birth: created by LucasNan on 20210219 int getSampleRate(){ return this->sample_rate_; } //@brief: get the audio size //@param: void //@ret: Audio size //@birth: created by LucasNan on 20210219 float getAudioSize(){ return this->audio_size_; } private: AVFormatContext* input_AVFormat_context_; //Stream number unsigned int stream_numbers_; //Video stream index number unsigned int video_stream_index_; //Audio stream index number unsigned int audio_stream_index_; //(1) Overall std::string format_; //format std::string duration_; //duration //(2) For video int frame_rate_; //Frame rate int video_average_bit_rate_; //Average bitrate int width_; //Video width int height_; //Video height float video_size_; //Video stream size std::string video_format_; //Video coding format //(3) For audio std::string audio_format_; //Audio coding format int audio_average_bit_rate_; //Average audio bit rate int channel_nums; //Channels int sample_rate_; //sampling rate float audio_size_; //Audio stream size }; #endif // VIDEOINFORMATION_H
- Class implementation code (videoinformation.cpp)
// Copyright (c) 2021 LucasNan <nanche@mail.hfut.edu.cn> <www.kevinnan.org.cn> // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation // files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the // Software is furnished to do so, subject to the following // conditions: // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR // OTHER DEALINGS IN THE SOFTWARE. #include "videoinformation.h" VideoInformation::VideoInformation() { //Get dynamic memory input_AVFormat_context_ = avformat_alloc_context(); //input_AVFormat_context_ = NULL; } void VideoInformation::getVideoInfo(std::string file_path){ if(avformat_open_input(&input_AVFormat_context_, file_path.c_str(), 0, NULL) < 0){ std::cout<<"file open error!"<<std::endl; return; } if(avformat_find_stream_info(input_AVFormat_context_, NULL) < 0){ printf("error"); return ; } //Get the number of streams this->stream_numbers_ = input_AVFormat_context_->nb_streams; //Calculate video length int hours, mins, secs; secs = input_AVFormat_context_->duration / 1000000; mins = secs / 60; secs %= 60; hours = mins / 60; mins %= 60; //Format video length char duration_foramt_[128]; sprintf(duration_foramt_, "%d:%d:%d", hours, mins, secs); this->duration_ = duration_foramt_; //av_dump_format(input_AVFormat_context_, 0, file_path.c_str(), 0); //Get the packaging format of the input video std::cout<<"format: "<<input_AVFormat_context_->streams[0]->codecpar->format<<std::endl; std::cout<<"bit rate: "<<input_AVFormat_context_->bit_rate/1000.0<<std::endl; AVInputFormat* infoFormat = input_AVFormat_context_->iformat; this->format_ = infoFormat->name; //Traverse the video stream respectively for(unsigned int i = 0; i < stream_numbers_; i++){ //Take out a stream and generate an AVStream object AVStream* input_stream = input_AVFormat_context_->streams[i]; //AVDictionaryEntry *lang = av_dict_get(input_stream->metadata, "language", NULL, 0); //std::cout<<"ddd: "<<lang->value<<std::endl; //Determine whether it is a video stream if(input_stream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO){ //avg_ frame_ Rate - > avrational, //avg_frame_rate.num: molecule //avg_frame_rate.den: Female //Get video frame rate this->frame_rate_ = input_stream->avg_frame_rate.num / input_stream->avg_frame_rate.den; //Take out the coding parameters in the video stream and generate the AVCodecParamters object AVCodecParameters* codec_par = input_stream->codecpar; //The video width, height, bit rate and video size are obtained by using the coding parameter object AVCdecParamters this->width_ = codec_par->width; this->height_ = codec_par->height; this->video_average_bit_rate_ = codec_par->bit_rate/1000; this->video_size_ = this->video_average_bit_rate_ * secs / (8.0*1024); //Using avcodec_ paramters_ to_ The context() function generates an AVCodecContext object //input_ Stream - > codec has been eliminated. It is not recommended to generate AVCodecContext in this way AVCodecContext* avctx_video; avctx_video = avcodec_alloc_context3(NULL); int ret = avcodec_parameters_to_context(avctx_video, codec_par); if (ret < 0) { avcodec_free_context(&avctx_video); return; } //Use AVCodecContext to get video coding format (not recommended) char buf[128]; avcodec_string(buf, sizeof(buf), avctx_video, 0); //Use AVCodecParameters to get the video coding method this->video_format_ = avcodec_get_name((codec_par->codec_id)); //Determine whether the audio stream is }else if(input_stream->codecpar->codec_type == AVMEDIA_TYPE_AUDIO){ //Generate AVcodecParamters object AVCodecParameters* codec_par = input_stream->codecpar; AVCodecContext* avctx_audio; avctx_audio = avcodec_alloc_context3(NULL); int ret = avcodec_parameters_to_context(avctx_audio, codec_par); if(ret < 0){ avcodec_free_context(&avctx_audio); return; } this->audio_format_ = avcodec_get_name(avctx_audio->codec_id); this->audio_average_bit_rate_ = codec_par->bit_rate / 1000; this->channel_nums = codec_par->channels; this->sample_rate_ = codec_par->sample_rate; this->audio_size_ = this->audio_average_bit_rate_ * secs / (8.0*1024); } } }
- main.cpp code
// Copyright (c) 2021 LucasNan <nanche@mail.hfut.edu.cn> <www.kevinnan.org.cn> // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation // files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the // Software is furnished to do so, subject to the following // conditions: // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR // OTHER DEALINGS IN THE SOFTWARE. #include <QCoreApplication> #include <iostream> #include "videoinformation.h" int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); //const char* file = "F:/google/durant.mp4"; const char* file = "F:/google/Beautiful-Ambient-Mix.mp4"; VideoInformation* v1 = new VideoInformation(); v1->getVideoInfo(file); std::cout<<"duration: "<<v1->getDuration()<<std::endl<< "format: "<<v1->getFormat()<<std::endl<< "video frame rate: "<<v1->getFrameRate()<<std::endl<< "video bit rate: "<<v1->getVideoAverageBitRate()<<std::endl<< "video format: "<<v1->getVideoFormat()<<std::endl<< "video width: "<<v1->getWidth()<<std::endl<< "video height: "<<v1->getHeight()<<std::endl<< "video size: "<<v1->getVideoSize()<<std::endl<< "audio bit rate: "<<v1->getAudioAverageBitRate()<<std::endl<< "audio format: "<<v1->getAudioFormat()<<std::endl<< "audio size: "<<v1->getAudioSize()<<std::endl<< "audio smaple rate: "<<v1->getSampleRate()<<std::endl<< "audio channel numbers: "<<v1->getChannelNumbers()<<std::endl; return a.exec(); }
4. Why add extern"C" keyword?
Finally, I want to talk about a problem. Why use FFmpeg? Use the extern "C" keyword to contain the header file of FFmpeg.
The signature compiled in C language is_ Coder, while in C + + language, the generation of general compiler is similar to_ decode_float_float. Although there is no problem in the compilation phase, in the link phase, if the external "C" keyword is not added, the link will be generated_ decoder_float_float this method signature; If the keyword extern "C" is added, the method signature you are looking for is_ decoder. FFmpeg is written in C language. The method signatures generated when compiling FFmpeg are all C language type signatures. Therefore, the external "C" keyword must be added when referring to FFmpeg in C.