Implementation of H264 RTSP live via live555

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

The previous article described "H264 video via rtmp stream live", below will explain how to H264 live video live through RTSP.

The realization of the idea is to send the video stream to live555, by live555 to achieve the H264 data stream live.

The video capture module sends the H264 data frame to live555 through a FIFO queue. After receiving the client's RTSP playback request, the live555 begins to read the H264 video data from the FIFO and live it out via RTSP. The entire process is shown in the following diagram:


Adjust and modify Live555 mediaserver

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

Ww_h264videoservermediasubsession.h

Ww_h264videoservermediasubsession.cpp

Ww_h264videosource.h

Ww_h264videosource.cpp

The following is the source code for four documents:

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 () {//Based on FPS, calculate 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 was free software;  You can redistribute it and/or modify it under the terms of the GNU Lesser general public License as published by the free Software Foundation; Either version 2.1 of the License, or (at your option) any later version.

(see  

send the Rtspstream of the H264 video stream

/******************************************************************** 
filename:   RTSPStream.h
Created:    2013-08-01
Author:     firehood 
Purpose: live555    for RTSP live
H264 / 
#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 (1024x768 * 1024x768) 


class Crtspstream
{public
:
	crtspstream (void);
	~crtspstream (void);
Public:
	//Initialize
	bool Init ();
    Unload
	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: H264 RTSP live ***************************************************************** via 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.