Combined with the previous collection of v4l2 videos, live555 is used to publish real-time streams through rtsp. capture. h, capture. cpp, vcompress. h, vcompress. cpp should refer to the previous articles. here we only paste v4l2_x264_service.cpp [cpp] viewplaincopy # includestdio. h # define destdlib. h # includeunistd
Combined with the previous collection of v4l2 videos, live555 is used to publish real-time streams through rtsp. capture. h, capture. cpp, vcompress. h, vcompress. cpp should refer to the previous articles. here we only paste v4l2_x264_service.cpp [cpp] view plaincopy # includestdio. h # define destdlib. h # includeunistd
Combined with the previous collection of v4l2 videos, live555 is used to publish real-time streams through rtsp. capture. h, capture. cpp, vcompress. h, vcompress. cpp should refer to the previous articles. here we only paste v4l2_x264_service.cpp
[Cpp]View plaincopy
- # Include
- # Include
- # Include
- # Include
-
- # Include
- # Include
- # Include
-
- # Include
- # Include
-
- # Include "capture. h"
- # Include "vcompress. h"
-
- Static UsageEnvironment * _ env = 0;
-
- # Define SINK_PORT 3030
-
- # Define VIDEO_WIDTH 320
- # Define VIDEO_HEIGHT 240
- # Define FRAME_PER_SEC 5.0
-
- Pid_t gettid ()
- {
- Return syscall (SYS_gettid );
- }
-
-
- // Use webcam + x264
- Class WebcamFrameSource: public FramedSource
- {
- Void * mp_capture, * mp_compress; // v4l2 + x264 encoder
- Int m_started;
- Void * mp_token;
-
- Public:
- WebcamFrameSource (UsageEnvironment & env)
- : FramedSource (env)
- {
- Fprintf (stderr, "[% d] % s... calling \ n", gettid (), _ func __);
- Mp_capture = capture_open ("/dev/video0", VIDEO_WIDTH, VIDEO_HEIGHT, PIX_FMT_YUV420P );
- If (! Mp_capture ){
- Fprintf (stderr, "% s: open/dev/video0 err \ n", _ func __);
- Exit (-1 );
- }
-
- Mp_compress = vc_open (VIDEO_WIDTH, VIDEO_HEIGHT, FRAME_PER_SEC );
- If (! Mp_compress ){
- Fprintf (stderr, "% s: open x264 err \ n", _ func __);
- Exit (-1 );
- }
-
- M_started = 0;
- Mp_token = 0;
- }
-
- ~ WebcamFrameSource ()
- {
- Fprintf (stderr, "[% d] % s... calling \ n", gettid (), _ func __);
-
- If (m_started ){
- Envir (). taskScheduler (). unscheduleDelayedTask (mp_token );
- }
-
- If (mp_compress)
- Vc_close (mp_compress );
- If (mp_capture)
- Capture_close (mp_capture );
- }
-
- Protected:
- Virtual void doGetNextFrame ()
- {
- If (m_started) return;
- M_started = 1;
-
- // Calculate the wait time based on fps
- Double delay= 1000.0/FRAME_PER_SEC;
- Int to_delay = delay * 1000; // us
-
- Mp_token = envir (). taskScheduler (). scheduleDelayedTask (to_delay,
- GetNextFrame, this );
- }
[Cpp]View plaincopy
- Virtual unsigned maxFrameSize () const // This is very important. If it is not set, it may cause getNextFrame () to show that the fMaxSize is smaller than the actual Encoding Frame, resulting in incomplete images.
[Cpp]View plaincopy
- {Return 100*1024 ;}
[Cpp]View plaincopy
- Private:
- Static void getNextFrame (void * ptr)
- {
- (WebcamFrameSource *) ptr)-> getNextFrame1 ();
- }
-
- Void getNextFrame1 ()
- {
- // Capture:
- Picture pic;
- If (capture_get_picture (mp_capture, & pic) <0 ){
- Fprintf (stderr, "===% s: capture_get_picture err \ n", _ func __);
- M_started = 0;
- Return;
- }
-
- // Compress
- Const void * outbuf;
- Int outlen;
- If (vc_compress (mp_compress, pic. data, pic. stride, & outbuf, & outlen) <0 ){
- Fprintf (stderr, "===% s: vc_compress err \ n", _ func __);
- M_started = 0;
- Return;
- }
-
- Int64_t pts, dts;
- Int key;
- Vc_get_last_frame_info (mp_compress, & key, & pts, & dts );
-
- // Save outbuf
- Gettimeofday (& fPresentationTime, 0 );
- FFrameSize = outlen;
- If (fFrameSize> fMaxSize ){
- FNumTruncatedBytes = fFrameSize-fMaxSize;
- FFrameSize = fMaxSize;
- }
- Else {
- FNumTruncatedBytes = 0;
- }
-
- Memmove (fTo, outbuf, fFrameSize );
-
- // Notify
- AfterGetting (this );
-
- M_started = 0;
- }
- };
-
- Class WebcamOndemandMediaSubsession: public OnDemandServerMediaSubsession
- {
- Public:
- Static WebcamOndemandMediaSubsession * createNew (UsageEnvironment & env, FramedSource * source)
- {
- Return new WebcamOndemandMediaSubsession (env, source );
- }
-
- Protected:
- WebcamOndemandMediaSubsession (UsageEnvironment & env, FramedSource * source)
- : OnDemandServerMediaSubsession (env, True) // reuse the first source
- {
- Fprintf (stderr, "[% d] % s... calling \ n", gettid (), _ func __);
- Mp_source = source;
- Mp_sdp_line = 0;
- }
-
- ~ WebcamOndemandMediaSubsession ()
- {
- Fprintf (stderr, "[% d] % s... calling \ n", gettid (), _ func __);
- If (mp_sdp_line) free (mp_sdp_line );
- }
-
- Private:
- Static void afterPlayingDummy (void * ptr)
- {
- Fprintf (stderr, "[% d] % s... calling \ n", gettid (), _ func __);
- // OK
- WebcamOndemandMediaSubsession * This = (WebcamOndemandMediaSubsession *) ptr;
- This-> m_done = 0xff;
- }
-
- Static void chkForAuxSDPLine (void * ptr)
- {
- WebcamOndemandMediaSubsession * This = (WebcamOndemandMediaSubsession *) ptr;
- This-> chkForAuxSDPLine1 ();
- }
-
- Void chkForAuxSDPLine1 ()
- {
- Fprintf (stderr, "[% d] % s... calling \ n", gettid (), _ func __);
- If (mp_dummy_rtpsink-> auxSDPLine ())
- M_done = 0xff;
- Else {
- Int delay = 100*1000; // 100 ms
- NextTask () = envir (). taskScheduler (). scheduleDelayedTask (delay,
- ChkForAuxSDPLine, this );
- }
- }
-
- Protected:
- Virtual const char * getAuxSDPLine (RTPSink * sink, FramedSource * source)
- {
- Fprintf (stderr, "[% d] % s... calling \ n", gettid (), _ func __);
- If (mp_sdp_line) return mp_sdp_line;
-
- Mp_dummy_rtpsink = sink;
- Mp_dummy_rtpsink-> startPlaying (* source, 0, 0 );
- // Mp_dummy_rtpsink-> startPlaying (* source, afterPlayingDummy, this );
- ChkForAuxSDPLine (this );
- M_done = 0;
- Envir (). taskScheduler (). doEventLoop (& m_done );
- Mp_sdp_line = strdup (mp_dummy_rtpsink-> auxSDPLine ());
- Mp_dummy_rtpsink-> stopPlaying ();
-
- Return mp_sdp_line;
- }
-
- Virtual RTPSink * createNewRTPSink (Groupsock * rtpsock, unsigned char type, FramedSource * source)
- {
- Fprintf (stderr, "[% d] % s... calling \ n", gettid (), _ func __);
- Return hsf-videortpsink: createNew (envir (), rtpsock, type );
- }
-
- Virtual FramedSource * createNewStreamSource (unsigned sid, unsigned & bitrate)
- {
- Fprintf (stderr, "[% d] % s... calling \ n", gettid (), _ func __);
- Bitrate = 500;
- Return hsf-videostreamframer: createNew (envir (), new WebcamFrameSource (envir ()));
- }
-
- Private:
- FramedSource * mp_source; // corresponding to WebcamFrameSource
- Char * mp_sdp_line;
- RTPSink * mp_dummy_rtpsink;
- Char m_done;
- };
-
- Static void test_task (void * ptr)
- {
- Fprintf (stderr, "test: task... \ n ");
- _ Env-> taskScheduler (). scheduleDelayedTask (100000, test_task, 0 );
- }
-
- Static void test (UsageEnvironment & env)
- {
- Fprintf (stderr, "test: begin... \ n ");
-
- Char done = 0;
- Int delay = 100*1000;
- Env. taskScheduler (). scheduleDelayedTask (delay, test_task, 0 );
- Env. taskScheduler (). doEventLoop (& done );
-
- Fprintf (stderr, "test: end... \ n ");
- }
-
- Int main (int argc, char ** argv)
- {
- // Env
- TaskScheduler * schedew = basictaskschedew: createNew ();
- _ Env = BasicUsageEnvironment: createNew (* schedew );
-
- // Test
- // Test (* _ env );
-
- // Rtsp server
- RTSPServer * rtspServer = RTSPServer: createNew (* _ env, 8554 );
- If (! RtspServer ){
- Fprintf (stderr, "ERR: create RTSPServer err \ n ");
- : Exit (-1 );
- }
-
- // Add live stream
- Do {
- WebcamFrameSource * webcam_source = 0;
-
- ServerMediaSession * sms = ServerMediaSession: createNew (* _ env, "webcam", 0, "Session from/dev/video0 ");
- Sms-> addSubsession (WebcamOndemandMediaSubsession: createNew (* _ env, webcam_source ));
- RtspServer-> addServerMediaSession (sms );
-
- Char * url = rtspServer-> rtspURL (sms );
- * _ Env <"using url \" "<url <" \ "\ n ";
- Delete [] url;
- } While (0 );
-
- // Run loop
- _ Env-> taskScheduler (). doEventLoop ();
-
- Return 1;
- }
Live555 + libavcodec + libswscale + libx264 is required. The client uses vlc, mplayer, quicktime ,.....