I am new to video decoding/encoding. Currently I have a task to test the video transmission for a network coding. The network coding programme was already done.
Firstly I tried to divide the video into frames in opencv, and transmit the frames, but after division, I found a 3MB video are converted to 80MB total size frames!! which is not efficient for transmission. Is there any better way to do the video transmission? Can any pros provide me a sample code in C++? I be told that cannot directly put video into buff due to the transmission bandwidth limitation. I am wondering using the inter frame difference to reduce the transmission file size but I do not know ht to do this in C++.
Here is my code for video divide into frames.
#include "opencv2/highgui/highgui.hpp"
#include <iostream>
using namespace cv;
using namespace std;
int main(int argc, char* argv[])
{
VideoCapture cap("/home/yonghao/Documents/50MbitMJPEG1080p.mp4"); // open the video file for reading
double fps = cap.get(CV_CAP_PROP_FPS); //get the frames per seconds of the video
int numFrames = cap.get(CV_CAP_PROP_FRAME_COUNT); // get the total number of frames
cout << "Frame per seconds : " << fps << endl;
cout << "Total Frame Numbers : " << numFrames << endl;
namedWindow("MyVideo",CV_WINDOW_AUTOSIZE); //create a window called "MyVideo"
int frame_number = 1;
while(frame_number<=numFrames)
{
Mat frame;
bool bSuccess = cap.read(frame); // read a new frame from video
if (!bSuccess) //if not success, break loop
{
cout << "Cannot read the frame from video file" << endl;
break;
}
imshow("MyVideo", frame); //show the frame in "MyVideo" window
//save frame
stringstream ss;
string name = "/home/yonghao/Documents/Frames/frame_";
string type = ".jpg";
ss<<name<<(frame_number)<<type;
string filename = ss.str();
ss.str("");
imwrite(filename, frame);
cout << "Frame " << frame_number << " has been generated." << endl;
frame_number++;
//user exit by press ESC button
if(waitKey(30) == 27) //wait for 'esc' key press for 30 ms. If 'esc' key is pressed, break loop
{
cout << "esc key is pressed by user" << endl;
break;
}
}
return 0;
}
If the bitrate of your video is too high for your bandwidth, you need to recompress it, using a standard video codec, for example h264. You can do that with the ffmpeg program, using something like :
This will encode with default options and a constant quality (crf parameter, the lower the higher quality), see here for the options of h264 encoder, in your case you may prefer to use constant bitrate instead of constant quality.
Reading the video at correct speed and streaming it on the network would be possible in c with libavformat library (part of ffmpeg libraries), but probably complex for a beginner.
One simpler solution would be to pipe the output of a ffmpeg command to your program that does the network coding.
For example:
This will read the encoded video file and send the raw video stream to your network encoding program (here network_encode read data from standard input, apply your network coding and send it)
On the receiver, you can do something similar to visualize your video (here network_decode receive the data from the network, decode it, and write result to standard output):