Push off
Processes: initializing, connecting to servers, sending data
This part mainly uses the librtmp, because is uses other people to encapsulate the good library, generally relatively simple initialization
Simply call the function
rtmp = Rtmp_alloc ();
Rtmp_init (RTMP);
connecting to a server
The four functions represent: Set the URL, make yourself a sender, build a netconnection, build a NetStream
Rtmp_setupurl (RTMP, url);
Rtmp_enablewrite (RTMP);
Rtmp_connect (RTMP, NULL);
Rtmp_connectstream (mrtmp, 0);
Send Data
Constantly remove the rtmp package from the queue, plus the timestamp and flow ID, and then send to the server, frame rate control is located in the encoding thread, so there is no time to calculate, directly with the time stamp to send, and because it is not a good time to calculate, there is the queue is blocked queue
while (true) {
rtmppacket& packet = Queue.front ();
Packet.m_ninfofield2 = rtmp->m_stream_id;
Packet.m_ntimestamp = Rtmp_gettime ();
Rtmp_sendpacket (RTMP, &packet, 1);
Queue.pop ();
}
Main program
Mainly divided into: Video coding thread, audio coding thread, main thread (send thread) Video Coding thread
According to the frame rate to calculate the interval time, and then the video metadata rtmp packet to save for multiple send, from the video source to get frames, to determine whether it is a key frame, if it is the first send metadata, after the encoding package to send data, the final comparison of time and time to decide whether to wait
const int interval = 1000/fps; int bytes; char *buf, *frame;
Rtmppacket packet, Meta;
H264rtmppackager Packager;
Std::chrono::milliseconds duration;
std::p air<int, char*> result;
Meta = Encoder.getmetadata ();
BUF = Pool.get (1024);
Packet = Packager.metadata (buf, Result.second, Result.first);
Auto last = Std::chrono::system_clock::now ();
while (frame = Source.getnextframe ())!= NULL) {result = Source.encode (frame);
if (H264rtmppackager::iskeyframe (Result.second)) {Queue.push (meta, true);
} bytes = Packager.getbodylength (Result.first);
buf = pool.get (bytes);
Packet = Packager.pack (buf, Result.second, Result.first) queue.push (packet);
Duration = Std::chrono::d uration_cast<std::chrono::milliseconds> (Std::chrono::system_clock::now ()-last);
if (Duration < interval) {Msleep (interval-duration). Count ());
Last = Std::chrono::system_clock::now (); }
Audio Coded Threads
The steps are similar to the video coding thread, except that there is no need to wait because the audio source outputs frames based on the sample rate, where the metadata only needs to be sent once, so you don't have to save
int bytes;
char *buf;
Rtmppacket packet;
Aacrtmppackager Packager;
std::p air<int, char*> frame, result;
result = Encoder.getmetadata ();
BUF = Pool.get (128);
Packet = Packager.metadata (buf, Result.second, Result.first);
Queue.push (packet, true);
while (frame = Source.getnextframes ()). Second!= NULL) {Result
= Encoder.encode (Frame.first, frame.second);
if (result.first!= 0) {
bytes = packager.getbodylength (result.first);
buf = pool.get (bytes);
Packet = Packager.pack (buf, Result.second, Result.first);
Queue.push (packet);
}
Main thread
Create H264 Stream and AAC stream, then turn on video encoding thread and audio encoding thread
Packetqueue queue;
MemoryPool Pool;
V4l2source v4l2 (width, height);
Pcmsource PCM;
Yuy2converter Converter (yuy2_cvt_rgb24);
Motiondetector detector;
Filteredvideosource VideoSource (V4L2);
Videosource.addfilter (&converter);
Videosource.addfilter (&detector);
Rtmppublisher Publisher (queue, pool);
Publisher.connect (URL);
H264stream videostream (VideoSource, queue, pool, fps, bitrate);
Aacstream Audiostream (PCM, queue, pool);
Std::thread Videoencodethread (&h264stream::run, &videostream);
Std::thread Audioencodethread (&aacstream::run, &audiostream);
Publisher.run ();
PostScript
At this point, the simple push program is complete, project overall relatively simple, basically is in the call to the Third-party library, but generally learned many things, for the previously not understand the audio and video coding, there are some understanding, but also the first encounter producer-consumer situation, although the situation here is relatively simple, Only one consumer
Their test environment is computer Ubuntu and raspberry Pie Raspbian, about the use of the library, OPENCV3 should be required to compile the installation, Raspberry Pie LIBFAAC may also need to compile the installation
RTMP server with SRS, configuration method and online can be very simple to search