├── README.md ├── RtspClient.pro ├── ffmpegdecoder.cpp ├── ffmpegdecoder.h └── main.cpp /README.md: -------------------------------------------------------------------------------- 1 | # RTSP-Client-FFMPEG-OpenCV-ON-QT 2 | 3 | ## Prerequisite 4 | Install libraries to use ffmpeg 5 | ``` 6 | sudo apt-get install libavcodec-dev 7 | sudo apt-get install libavformat-dev 8 | sudo apt-get install libavutil-dev 9 | sudo apt-get install libswscale-dev 10 | sudo apt-get install libswresample-dev 11 | sudo apt-get install libavdevice-dev 12 | sudo apt-get install libavfilter-dev 13 | ``` 14 | Install qtcreator 15 | ``` 16 | sudo apt-get install qtcreator 17 | ``` 18 | if you want to process only a image except a packet, you can easily process a image by using the below code. 19 | 20 | ``` 21 | 22 | #include 23 | #include 24 | 25 | int main() 26 | { 27 | cv::VideoCapture vc("your rtsp address"); 28 | 29 | if(vc.isOpened()) 30 | { 31 | cv::Mat src; 32 | 33 | while(vc.read(src)) 34 | { 35 | cv::imshow("src",src); 36 | cv::waitKey(10); 37 | } 38 | } 39 | 40 | return 0; 41 | } 42 | 43 | ``` 44 | -------------------------------------------------------------------------------- /RtspClient.pro: -------------------------------------------------------------------------------- 1 | TEMPLATE = app 2 | CONFIG += console c++11 3 | CONFIG -= app_bundle 4 | CONFIG -= qt 5 | 6 | 7 | INCLUDEPATH += /usr/local/include/opencv 8 | LIBS += -L/usr/local/lib -lopencv_core -lopencv_imgcodecs -lopencv_imgproc -lopencv_highgui -lopencv_videoio 9 | 10 | INCLUDEPATH += /usr/include/ 11 | LIBS += -L/usr/lib/aarch64-linux-gnu -lpthread -lavcodec -lavformat -lavutil -lswscale -lswresample -lavdevice -lavfilter 12 | 13 | SOURCES += main.cpp \ 14 | ffmpegdecoder.cpp 15 | 16 | HEADERS += \ 17 | ffmpegdecoder.h 18 | -------------------------------------------------------------------------------- /ffmpegdecoder.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // ffmpegdecoder.h 3 | // ffmpeg RTSP Client 4 | // 5 | // Created by Yonghye Kwon on 9/14/18. 6 | // Copyright (c) Freeeeeeeeeeeeeee 7 | // 8 | 9 | #include "ffmpegdecoder.h" 10 | 11 | using namespace std; 12 | 13 | FFmpegDecoder::FFmpegDecoder(std::string path) 14 | :bConnected(false) 15 | { 16 | this->path = path; 17 | } 18 | 19 | FFmpegDecoder::~FFmpegDecoder() 20 | { 21 | destroy(); 22 | } 23 | 24 | void FFmpegDecoder::connect() 25 | { 26 | avformat_network_init(); 27 | av_register_all(); 28 | 29 | pFormatCtx = avformat_alloc_context(); 30 | 31 | AVDictionary *avdic=NULL; 32 | char option_key[]="rtsp_transport"; 33 | char option_value[]="tcp"; 34 | 35 | av_dict_set(&avdic,option_key,option_value,0); 36 | char option_key2[]="max_delay"; 37 | char option_value2[]="100"; 38 | 39 | av_dict_set(&avdic,option_key2,option_value2,0); 40 | 41 | if (avformat_open_input(&pFormatCtx, path.c_str(), NULL, &avdic) != 0) 42 | { 43 | std::cout << "can't open the file." << std::endl; 44 | bConnected = false; 45 | return ; 46 | } 47 | 48 | if (avformat_find_stream_info(pFormatCtx, NULL) < 0) 49 | { 50 | std::cout << "can't find stream infomation" << std::endl; 51 | bConnected = false; 52 | return ; 53 | } 54 | 55 | videoStream = -1; 56 | 57 | 58 | for (unsigned int i = 0; i < pFormatCtx->nb_streams; i++) 59 | { 60 | if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) 61 | { 62 | videoStream = i; 63 | } 64 | } 65 | 66 | if (videoStream == -1) 67 | { 68 | std::cout << "can't find a video stream" << std::endl; 69 | bConnected = false; 70 | return ; 71 | } 72 | 73 | pCodecCtx = pFormatCtx->streams[videoStream]->codec; 74 | pCodec = avcodec_find_decoder(pCodecCtx->codec_id); 75 | 76 | pCodecCtx->bit_rate = 0; 77 | pCodecCtx->time_base.num = 1; 78 | pCodecCtx->time_base.den = 10; 79 | pCodecCtx->frame_number = 1; 80 | 81 | 82 | if (pCodec == NULL) 83 | { 84 | std::cout << "can't find a codec" << std::endl; 85 | bConnected = false; 86 | return ; 87 | } 88 | 89 | if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0) 90 | { 91 | std::cout << "can't open a codec" << std::endl; 92 | bConnected = false; 93 | return ; 94 | } 95 | 96 | pFrame = av_frame_alloc(); 97 | pFrameBGR = av_frame_alloc(); 98 | 99 | 100 | imgConvertCtx = sws_getContext(pCodecCtx->width, pCodecCtx->height, 101 | pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height, 102 | AV_PIX_FMT_BGR24, SWS_BICUBIC, NULL, NULL, NULL); 103 | 104 | int numBytes = avpicture_get_size(AV_PIX_FMT_BGR24, pCodecCtx->width,pCodecCtx->height); 105 | 106 | outBuffer = (uint8_t *) av_malloc(numBytes * sizeof(uint8_t)); 107 | avpicture_fill((AVPicture *) pFrameBGR, outBuffer, AV_PIX_FMT_BGR24, 108 | pCodecCtx->width, pCodecCtx->height); 109 | 110 | packet = (AVPacket *) malloc(sizeof(AVPacket)); 111 | av_new_packet(packet, pCodecCtx->width * pCodecCtx->height); 112 | 113 | bConnected = true; 114 | } 115 | 116 | void FFmpegDecoder::decode() 117 | { 118 | std::chrono::milliseconds duration(5); 119 | 120 | while (av_read_frame(pFormatCtx, packet) >= 0) 121 | { 122 | if (packet->stream_index == videoStream) 123 | { 124 | int got_picture = 0; 125 | int ret = avcodec_decode_video2(pCodecCtx, pFrame, &got_picture,packet); 126 | 127 | if (ret < 0) 128 | { 129 | std::cout << "decode error.\n" << std::endl; 130 | break ; 131 | } 132 | 133 | if (got_picture) 134 | { 135 | sws_scale(imgConvertCtx, 136 | (uint8_t const * const *) pFrame->data, 137 | pFrame->linesize, 0, pCodecCtx->height, pFrameBGR->data, 138 | pFrameBGR->linesize); 139 | 140 | cv::Mat img(pFrame->height, 141 | pFrame->width, 142 | CV_8UC3, 143 | pFrameBGR->data[0]); 144 | 145 | mtx.lock(); 146 | decodedImgBuf.push_back(img); 147 | mtx.unlock(); 148 | } 149 | } 150 | av_free_packet(packet); 151 | std::this_thread::sleep_for(duration); 152 | } 153 | bConnected = false; 154 | } 155 | 156 | void FFmpegDecoder::destroy() 157 | { 158 | av_free(outBuffer); 159 | av_free(pFrameBGR); 160 | avcodec_close(pCodecCtx); 161 | avformat_close_input(&pFormatCtx); 162 | } 163 | -------------------------------------------------------------------------------- /ffmpegdecoder.h: -------------------------------------------------------------------------------- 1 | // 2 | // ffmpegdecoder.h 3 | // ffmpeg RTSP Client 4 | // 5 | // Created by Yonghye Kwon on 9/14/18. 6 | // Copyright (c) Freeeeeeeeeeeeeee 7 | // 8 | 9 | #ifndef ffmpegdecoder_H 10 | #define ffmpegdecoder_H 11 | 12 | #include 13 | #include 14 | 15 | #include 16 | #include 17 | #include 18 | 19 | #include 20 | 21 | extern "C" 22 | { 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | } 30 | 31 | class FFmpegDecoder 32 | { 33 | public: 34 | FFmpegDecoder(std::string); 35 | ~FFmpegDecoder(); 36 | 37 | void connect(); 38 | void decode(); 39 | 40 | bool isConncected() const {return bConnected;} 41 | 42 | std::deque decodedImgBuf; 43 | std::mutex mtx; 44 | 45 | private: 46 | 47 | void destroy(); 48 | 49 | AVFormatContext *pFormatCtx; 50 | AVCodecContext *pCodecCtx; 51 | AVCodec *pCodec; 52 | AVFrame *pFrame, *pFrameBGR; 53 | AVPacket *packet; 54 | uint8_t *outBuffer; 55 | SwsContext *imgConvertCtx; 56 | 57 | int videoStream; 58 | 59 | std::string path; 60 | 61 | bool bConnected; 62 | }; 63 | 64 | #endif 65 | -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "ffmpegdecoder.h" 3 | 4 | 5 | class ImageProc 6 | { 7 | 8 | public: 9 | ImageProc(){} 10 | ~ImageProc(){} 11 | void process(FFmpegDecoder& decoder); 12 | }; 13 | 14 | 15 | void ImageProc::process(FFmpegDecoder &decoder) 16 | { 17 | while(decoder.isConncected()) 18 | { 19 | cv::Mat src; 20 | 21 | decoder.mtx.lock(); 22 | if(!decoder.decodedImgBuf.empty()) 23 | { 24 | src = decoder.decodedImgBuf.front().clone(); 25 | decoder.decodedImgBuf.pop_front(); 26 | // std::cout <<"img buffer size = "<< decoder.decodedImgBuf.size() << std::endl; 27 | } 28 | decoder.mtx.unlock(); 29 | 30 | if(!src.empty()) 31 | { 32 | //do your stuff... 33 | 34 | // 35 | 36 | cv::imshow("src", src); 37 | cv::waitKey(10); 38 | 39 | src.release(); 40 | } 41 | } 42 | } 43 | 44 | int main() 45 | { 46 | FFmpegDecoder decoder("your rstp address"); 47 | 48 | decoder.connect(); 49 | if(decoder.isConncected()) 50 | { 51 | ImageProc imgProc; 52 | 53 | std::thread t1{&FFmpegDecoder::decode, &decoder}; 54 | imgProc.process(decoder); 55 | 56 | t1.join(); 57 | } 58 | return 0; 59 | } 60 | --------------------------------------------------------------------------------