RTSP to rtmp and save as MP4 file

Source: Internet
Author: User
Tags strcmp
A background:
Users need to watch the video through flash or mobile phone, and most cameras are RTSP protocol, so need to do a relay.
Resources:
http://blog.csdn.net/firehood_/article/details/8813587
http://blog.csdn.net/firehood_/article/details/8783589
These two articles detail the Mp4v2 save the file and the 264 files through the rtmp live, the two aspects of interest can be directly read the two articles. This article is only read the two articles in 264 transfer forwarding to read RTSP forwarding, a little more live555 content, the other basic, just slightly adjusted a little bit interface part.

Two processes:
1 live555 video from the camera, in order to facilitate the explanation here only discusses the video.
2 mp4v2 save into. mp4
3 librtmp upload video stream to Nginx
4 Web users viewed via flash


Three technical explanations:
1 live555 Read RTSP video, you can refer to the PlayCommon.cpp or TestRTSPClient.cpp, the former full-featured, the latter concise some, but support multi-channel access at the same time. If you write RTSP Client, the environment is not very complex, you can refer to this code.
RTSP receive H264 video, whether read or write files or send streams, the main problem is the SPS and PPS above. These two names do not explain here, Google itself, here only how to take these two parameters.
Read live source, note that there is a paragraph in the playCommon.cpp:


else if (strcmp (Subsession->mediumname (), "video") = = 0 &&
(strcmp (Subsession->codecname (), "H264") = = 0)) {
For H.264 video stream, we use a special sink which adds ' Start codes ', and (at the start) the SPS and PPS NAL units:
Filesink = H264videofilesink::createnew (*env, Outfilename,
Subsession->fmtp_spropparametersets (),
Filesinkbuffersize, Onefileperframe);
}


Here call H264videofilesink Save 264 files, playback Normal, so we need to study the H264videofilesink source.
Just notice the Aftergettingframe function inside the H264VideoFileSink.cpp, as follows:
if (!fhavewrittenfirstframe) {
If We have Pps/sps NAL units encoded in a "Sprop parameter string", prepend this to the file:
unsigned numsproprecords;
sproprecord* sproprecords = Parsespropparametersets (Fspropparametersetsstr, numsproprecords);
for (unsigned i = 0; i < numsproprecords; ++i) {
AddData (Start_code, 4, presentationtime);
AddData (Sproprecords[i].spropbytes, Sproprecords[i].sproplength, presentationtime);
}
Delete[] Sproprecords;
Fhavewrittenfirstframe = True; For next time
}


Write the input data to the file and the start code in front:
AddData (Start_code, 4, presentationtime);

The annotation is very obvious, here is a simple point:
for (unsigned i = 0; i < numsproprecords; ++i) {
AddData (Start_code, 4, presentationtime);
AddData (Sproprecords[i].spropbytes, Sproprecords[i].sproplength, presentationtime);
}
The sproprecords here are the parameters that come in from the outside: Subsession->fmtp_spropparametersets (), from the name of the SPS and PPS together content.
Debug can be found, numsproprecords==2,for cycle two times, the first is the SPS, the second is PPS. Keep these two in mind, save 264 and send rtmp when written in the corresponding position, all the work is basically done.

2 Mp4v2 API is very simple, there is nothing to say, the only note is the first to read the video from the SPS width and height. You can refer to the following code.
3 Librtmp, also very simple, just pay attention to the first to send SPS and PPS
4 Live server with Nginx+nginx_rtmp_module, Google, a lot of documents.


Four operating environment: CentOS6.4 and Ubuntu 12 under normal operation. Windows can also, multiple platforms need type unification, such as uint,byte,uint32_t, uint8_t, a little change on the good.


Five RTSP Partial simple code Demo:
1 testRTSPClient.cpp code to copy out, put in their own code, RTSP receive function on the OK. Just a little change, and here's the change:


void Continueaftersetup (rtspclient* rtspclient, int resultcode, char* resultstring) {
Here, add:
Temporarily process video only
if (strcmp (Scs.subsession->mediumname (), "video") = = 0 &&
(strcmp (Scs.subsession->codecname (), "H264") = = 0))
{
dummysink* Pvideosink = dummysink::createnew (env, *scs.subsession, Rtspclient->url ());
Pvideosink->sps = Scs.subsession->fmtp_spropparametersets ();


Scs.subsession->sink = Pvideosink;
}
This part of the code reference PlayComm.cpp, the SPS is a string variable, for demonstration convenience, directly declared public, where the SPS PPS content as a string to Dummysink.

1280*760*3
#define Dummy_sink_receive_buffer_size 2764800
uint8_t* buff = NULL;
struct Timeval start_time;
unsigned numsproprecords;
sproprecord* sproprecords = NULL;


Dummysink::D ummysink (usageenvironment& env, mediasubsession& subsession, char const* streamid)
: Mediasink (ENV),
Fsubsession (subsession) {
Fstreamid = StrDup (Streamid);
Freceivebuffer = new U_int8_t[dummy_sink_receive_buffer_size];


Buff = new U_int8_t[dummy_sink_receive_buffer_size];
Gettimeofday (&start_time, NULL);
}
Dummysink::~dummysink () {
Delete[] Freceivebuffer;
Delete[] Fstreamid;
delete []buff;
}


void Dummysink::aftergettingframe (unsigned framesize, unsigned numtruncatedbytes,
struct Timeval presentationtime, unsigned/*durationinmicroseconds*/)
{


struct Timeval cur;
Gettimeofday (&cur, NULL);


static unsigned char const start_code[4] = {0x00, 0x00, 0x00, 0x01};
if (sproprecords = NULL)
{
These lines of code from H264VideoFileSink.cpp, first saved into sps.264 is to consider the time to save the file and live is not necessarily when the start of the local cache first.
Of course it can be saved in memory.
file* Pfsps = fopen ("sps.264", "WB");
Sproprecords = Parsespropparametersets (Sps.c_str (), numsproprecords);
The SPS here is a string, as mentioned in the previous Continueaftersetup code.
for (unsigned i = 0; i < numsproprecords; ++i)
{
if (Pfsps)
{
Fwrite (Start_code, 1, 4, Pfsps);
Fwrite (sproprecords[i].spropbytes, 1, sproprecords[i].sproplength, Pfsps);
}
}
Fclose (Pfsps);
Gettimeofday (&start_time, NULL);
}
int timestamp = (cur.tv_sec-start_time.tv_sec) *1000 + (CUR.TV_USEC-START_TIME.TV_USEC)/1000;


memset (Buff, ' 0 ', dummy_sink_receive_buffer_size);
memcpy (Buff, Start_code, 4);
memcpy (Buff+4, Freceivebuffer, framesize);

Callback (Buff, framesize+4, timestamp)//here itself implements a callback function that recalls the video data.

Continueplaying ();
}


Six: Mp4v2 saved into. mp4, you can refer to this article: http://blog.csdn.net/firehood_/article/details/8813587
However, there are several parameters that do not show how to get, you can handle a little, such as from the SPS read wide and high, reference: http://blog.csdn.net/firehood_/article/details/8783589,
Written by the same author, if carefully read his document, I do not need to read here.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.