Realization of H264 RTSP live broadcast via live555

Source: Internet
Author: User
Tags bool int size printf sleep usleep win32

The previous article introduced the "H264 video through the rtmp streaming", the following will explain how to H264 real-time video through the RTSP live.

The realization idea is to send the video stream to the live555, and the live555 to realize the H264 data stream live.

The video capture module sends the H264 data frame to live555 through the FIFO queue. After receiving the client's RTSP playback request, live555 reads the H264 video data from the FIFO and broadcasts it through RTSP. The entire process is shown in the following illustration:


Adjust and modify Live555 mediaserver

Download the live555 source, add four files to the media directory and modify the file live555MediaServer.cpp. The additional four documents are as follows:

Ww_h264videoservermediasubsession.h

Ww_h264videoservermediasubsession.cpp

Ww_h264videosource.h

Ww_h264videosource.cpp

The following is attached with the source code of four files:

Ww_h264videoservermediasubsession.h

#pragma once #include "livemedia.hh" #include "basicusageenvironment.hh" #include "groupsockhelper.hh" #include "Ondema Ndservermediasubsession.hh "#include" ww_h264videosource.h "class Ww_h264videoservermediasubsession:public ondemandservermediasubsession {public:ww_h264videoservermediasubsession (usageenvironment & env, FramedSource *
	SOURCE);

~ww_h264videoservermediasubsession (void);
	public:virtual Char const * GETAUXSDPLINE (Rtpsink * rtpsink, Framedsource * inputsource); Virtual Framedsource * Createnewstreamsource (unsigned clientsessionid, unsigned & estbitrate); "Estbitrate" is the stream ' s estimated bitrate, in kbps virtual Rtpsink * Createnewrtpsink (Groupsock * rtpgroupsock, U

	nsigned Char rtppayloadtypeifdynamic, Framedsource * inputsource);

	Static Ww_h264videoservermediasubsession * CREATENEW (usageenvironment & env, Framedsource * source);

	static void Afterplayingdummy (void * ptr);
	static void Chkforauxsdpline (void * ptr); void ChkforauxsdplinE1 ();
	Private:framedsource * M_PSOURCE;
	char * m_psdpline;
	Rtpsink * M_pdummyrtpsink;
Char M_done; };

Ww_h264videoservermediasubsession.cpp

#include "Ww_h264videoservermediasubsession.h" ww_h264videoservermediasubsession::ww_ H264videoservermediasubsession (Usageenvironment & env, Framedsource * source): Ondemandservermediasubsession (env
	, True) {m_psource = source;
M_psdpline = 0;
	} ww_h264videoservermediasubsession::~ww_h264videoservermediasubsession (void) {if (m_psdpline) {free (m_pSDPLine); } ww_h264videoservermediasubsession * Ww_h264videoservermediasubsession::createnew (UsageEnvironment & Env,

Framedsource * source) {return new ww_h264videoservermediasubsession (env, source);} Framedsource * Ww_h264videoservermediasubsession::createnewstreamsource (unsigned clientsessionid, unsigned &

Estbitrate) {return h264videostreamframer::createnew (EnviR (), New Ww_h264videosource (EnviR ())); Rtpsink * Ww_h264videoservermediasubsession::createnewrtpsink (Groupsock * rtpgroupsock, unsigned char Rtppayloadtypeifdynamic, Framedsource * inputsource) {return h264videortpsink::createnew (EnviR (), rtpGroupsOck, rtppayloadtypeifdynamic); } Char const * WW_H264VIDEOSERVERMEDIASUBSESSION::GETAUXSDPLINE (Rtpsink * rtpsink, Framedsource * inputsource) {if (m_p
	Sdpline) {return m_psdpline;

	} M_pdummyrtpsink = Rtpsink;
	Mp_dummy_rtpsink->startplaying (*source, Afterplayingdummy, this);

	M_pdummyrtpsink->startplaying (*inputsource, 0, 0);

	Chkforauxsdpline (this);

	M_done = 0;

	EnviR (). TaskScheduler (). Doeventloop (&m_done);

	M_psdpline = StrDup (M_pdummyrtpsink->auxsdpline ());

	M_pdummyrtpsink->stopplaying ();
return m_psdpline; } void Ww_h264videoservermediasubsession::afterplayingdummy (void * ptr) {ww_h264videoservermediasubsession * this = (WW

	_h264videoservermediasubsession *) ptr;
This->m_done = 0xFF; } void Ww_h264videoservermediasubsession::chkforauxsdpline (void * ptr) {ww_h264videoservermediasubsession * this = (WW_

	H264videoservermediasubsession *) ptr;
This->chkforauxsdpline1 (); } void Ww_h264videoservermediasubsession::chkforauxsdpline1 () {if (M_pdummyrtpsink->auxsdpline ())
	{m_done = 0xFF;  else {Double delay = 1000.0/(FRAME_PER_SEC);  ms int To_delay = delay * 1000;
	US nexttask () = EnviR (). TaskScheduler (). Scheduledelayedtask (To_delay, Chkforauxsdpline, this);
 }
}

Ww_h264videosource.h

#ifndef _ww_h264videosource_h
#define _WW_H264VIDEOSOURCE_H

#include "livemedia.hh"
#include " Basicusageenvironment.hh "
#include" groupsockhelper.hh "
#include" framedsource.hh "

#define Frame_per_ SEC

class Ww_h264videosource:public Framedsource
{public
:
	Ww_h264videosource (usageenvironment & env);
	~ww_h264videosource (void);

Public:
	virtual void dogetnextframe ();
	virtual unsigned int maxframesize () const;

	static void GetNextFrame (void * ptr);
	void Getframedata ();

Private:
	void *m_ptoken;
	char *m_pframebuffer;
	int  m_hfifo;
};

#endif


Ww_h264videosource.cpp

#include "ww_h264videosource.h" #include <stdio.h> #ifdef WIN32 #include <windows.h> #else #include <sys/ types.h> #include <sys/stat.h> #include <string.h> #include <fcntl.h> #include <unistd.h> # Include <limits.h> #endif #define FIFO_NAME "/tmp/h264_fifo" #define BUFFER_SIZE pipe_buf #define Rev_buf_siz E (1024*1024) #ifdef WIN32 #define MSLEEP (ms) sleep (ms) #else #define MSLEEP (ms) Usleep (ms*1000) #endif ww_h264v Ideosource::ww_h264videosource (Usageenvironment & env): Framedsource (env), M_ptoken (0), m_pFrameBuffer (0), m_
        Hfifo (0) {M_hfifo = open (fifo_name,o_rdonly);
	printf ("[MEDIA SERVER] Open FIFO result = [%d]\n", M_hfifo);
	if (M_hfifo = = 1) {return;
	} m_pFrameBuffer = new char[rev_buf_size];
		if (m_pFrameBuffer = = NULL) {printf ("[MEDIA SERVER] Error malloc data buffer failed\n");
	Return
} memset (M_pframebuffer,0,rev_buf_size); } ww_h264videosource::~ww_h264videosource (void) {if (M_hfifo{:: Close (M_HFIFO);

	} envir (). TaskScheduler (). Unscheduledelayedtask (M_ptoken);
		if (m_pFrameBuffer) {delete[] m_pframebuffer;
	m_pFrameBuffer = NULL;
printf ("[MEDIA SERVER] RTSP connection closed\n");  } void Ww_h264videosource::d ogetnextframe () {///per FPS, compute wait time double delay = 1000.0/(FRAME_PER_SEC * 2);  ms int To_delay = delay * 1000;
US m_ptoken = EnviR (). TaskScheduler (). Scheduledelayedtask (To_delay, GetNextFrame, this);

} unsigned int ww_h264videosource::maxframesize () const {return 1024*200;}

void Ww_h264videosource::getnextframe (void * ptr) {(Ww_h264videosource *) ptr)->getframedata ();}

    void Ww_h264videosource::getframedata () {gettimeofday (&fpresentationtime, 0);

	fframesize = 0;
	int len = 0;
	unsigned char buffer[buffer_size] = {0};
		while (len = Read (m_hfifo,buffer,buffer_size)) >0) {memcpy (M_pframebuffer+fframesize,buffer,len);
	Fframesize+=len; }//printf ("[MEDIA SERVER] Getframedata len = [%d],fmaxsize =[%d]\n ", fframesize,fmaxsize);

	Fill frame Data memcpy (fto,m_pframebuffer,fframesize);
		if (Fframesize > fmaxsize) {fnumtruncatedbytes = fframesize-fmaxsize;
	Fframesize = fmaxsize;
	else {fnumtruncatedbytes = 0;
} aftergetting (this);
 }

Modify the Live555MediaServer.cpp file as follows

/********** This library are free software;  Can redistribute it and/or modify it under the terms of the GNU lesser General public License as published by the Software Foundation; Either version 2.1 of the License, or (at your option) any later version.

(&LT;HTTP://WWW.GNU.ORG/COPYLEFT/LESSER.HTML&GT;.) This library is distributed in the hope that it'll be useful, but without any WARRANTY;  Without even the implied warranty of merchantability or FITNESS for A particular purpose.

The GNU Lesser general public License to more details. You are should have received a copy of the GNU Lesser General public License and this library; If not, write to the free Software Foundation, INC, Wuyi Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *********  *//Copyright (c) 1996-2013, Live Networks, Inc. All rights reserved//LIVE555 Media Server//Main program #include <BasicUsageEnvironment.hh> #include "dynamicrt Spserver.hh "#include" version.hh "#include" WW_h264videosource.h "#include" ww_h264videoservermediasubsession.h "int main (int argc, char** argv) {//Begin by setting
	Up our usage environment:taskscheduler* scheduler = basictaskscheduler::createnew ();

	usageenvironment* env = basicusageenvironment::createnew (*scheduler);
userauthenticationdatabase* authdb = NULL; #ifdef Access_control//To implement client ACCESS control to the RTSP server, do the FOLLOWING:AUTHDB = new userauthe
	Nticationdatabase; Authdb->adduserrecord ("username1", "Password1"); Replace these and real strings//Repeat the above with each <username>, <password> so you wish to Allo
w//access to the server.
	#endif//Create the RTSP server:rtspserver* rtspserver = rtspserver::createnew (*env, 554, authdb);
		if (Rtspserver = = NULL) {*env << "Failed to create RTSP server:" << env->getresultmsg () << "\ n";
	Exit (1);

	}//ADD live stream Ww_h264videosource * videosource = 0; Servermediasession * SMS = Servermediasession::createnew (*env, "Live", 0, "ww live test");
	Sms->addsubsession (Ww_h264videoservermediasubsession::createnew (*env, VideoSource));

	Rtspserver->addservermediasession (SMS);
	char * url = rtspserver->rtspurl (SMS);
	*env << "Using URL \" "<< url <<" \ \ n ";

	delete[] URL;

	Run Loop Env->taskscheduler (). Doeventloop ();

	Rtspserver->removeservermediasession (SMS);

	Medium::close (Rtspserver);

	Env->reclaim ();

	Delete Scheduler;
return 1;
 }

send the H264 video stream Rtspstream

/******************************************************************** 
filename:   RTSPStream.h
Created:    2013-08-01
Author:     firehood 
Purpose:
live555 H264 Live RTSP / 
#pragma once
#include <stdio.h>
#ifdef WIN32
#include <windows.h>
#else
#include <pthread.h>
#endif

#ifdef WIN32
typedef HANDLE       Threadhandle;
#define MSLEEP (ms) sleep   (ms)
#else
typedef unsigned int SOCKET;
typedef pthread_t    Threadhandle;
#define MSLEEP (MS)   Usleep (ms*1000)
#endif

#define FILEBUFSIZE (1024 * 1024) 


class Crtspstream
{public
:
	crtspstream (void);
	~crtspstream (void);
Public:
	//initialization of
	bool Init ();
    Uninstall
	void UnInit ();
	Send H264 file
	bool Sendh264file (const char *pfilename);
	Send H264 data frame
    int sendh264data (const unsigned char *data,unsigned int size);


/******************************************************************** Filename:RTSPStream.cpp created:2013-08-01 Author:firehood Purpose: Realize H264 RTSP live ***************************************************************** through live555 /#include "RTSPStream.h" #ifdef WIN32 #else #include <sys/types.h> #include <sys/stat.h> #include <st

ring.h> #include <fcntl.h> #include <unistd.h> #include <limits.h> #include <errno.h> #endif #define FIFO_NAME "/tmp/h264_fifo" #define buffersize pipe_buf crtspstream::crtspstream (void) {} crtspstream::~c Rtspstream (void) {} bool Crtspstream::init () {if (Access (FIFO_NAME,F_OK) = = 1) {int res = MKFIFO (fifo_name,0777)
		;
			if (res!= 0) {printf ("[Rtspstream] Create FIFO failed.\n");
		return false;
} return true;
		} void Crtspstream::uninit () {} bool Crtspstream::sendh264file (const char *pfilename) {if (Pfilename = = NULL) {
	return false; } FILE *FP = fopen (pFileName, "RB");
	if (!FP) {printf ("[Rtspstream] Error:open file%s failed!", pfilename);

	Fseek (FP, 0, Seek_set);
	unsigned char *buffer = new unsigned char[filebufsize];
	int pos = 0;

		while (1) {int readlen = fread (buffer+pos, sizeof (unsigned char), Filebufsize-pos, FP);
		if (readlen<=0) {break;

		} Readlen+=pos;
		int writelen = Sendh264data (Buffer,readlen);
		if (writelen<=0) {break;
		} memcpy (Buffer,buffer+writelen,readlen-writelen);

		pos = Readlen-writelen;
	Msleep (25);
	Fclose (FP);
	delete[] buffer;
return true;  }//Send H264 data frame int Crtspstream::sendh264data (const unsigned char *data,unsigned int size) {if (data = NULL) {return
	0; }//Open pipe with non_block mode int pipe_fd = open (Fifo_name, o_wronly|
	O_nonblock);
	printf ("[Rtspstream] Open FIFO result = [%d]\n", PIPE_FD);
	if (pipe_fd = = 1) {return 0;
	int send_size = 0;
	int remain_size = size; while (Send_size < size) {int Data_len = (remain_size<buffersize)?
		Remain_size:buffersize;
		int len = write (Pipe_fd,data+send_size,data_len);
			if (len = = 1) {static int resend_conut = 0; if (errno = = Eagain && ++resend_conut<=3) {printf ("[Rtspstream] write FIFO error,resend ...
				\ n ");
			Continue
			} resend_conut = 0;
			printf ("[Rtspstream] Write FIFO error,errorcode[%d],send_size[%d]\n", errno,send_size);
		Break
			else {send_size+= len;
		remain_size-= Len;
	} close (PIPE_FD);
	printf ("[Rtspstream] sendh264data datalen[%d], sendsize = [%d]\n", size,send_size);
return 0;
 }

test program Code

#include <stdio.h>
#include "RTSPStream.h"

int main (int argc,char* argv[])
{
	Crtspstream Rtspsender;
	BOOL BRet = Rtspsender.init ();
	Rtspsender.sendh264file ("e:\\ test video \\test.264");
	System ("pause");  
}

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.