live555传输音视频流

1、DynamicRTSPServer.cpp

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. ServerMediaSession* DynamicRTSPServer  
  2. ::lookupServerMediaSession(char const* streamName, Boolean isFirstLookupInSession) {  
  3.   // First, check whether the specified "streamName" exists as a local file:  
  4.   
  5.   // Next, check whether we already have a "ServerMediaSession" for this file:  
  6.   ServerMediaSession* sms = RTSPServer::lookupServerMediaSession(streamName);  
  7.   Boolean smsExists = sms != NULL;   
  8.   
  9.   FILE* fid = fopen(streamName, "rb");  
  10.   Boolean fileExists = fid != NULL;  
  11.     
  12.   if(strcmp(streamName,"live") == 0)  
  13.   {  
  14.         if (smsExists) {  
  15.           // "sms" was created for a file that no longer exists. Remove it:  
  16.           removeServerMediaSession(sms);  
  17.           sms = NULL;  
  18.         }  
  19.   
  20.         if (sms == NULL) {  
  21.           sms = createNewSMS(envir(), streamName, fid);   
  22.           addServerMediaSession(sms);  
  23.         }  
  24.   
  25.         return sms;          
  26.   }  
  27.     
  28.   // Handle the four possibilities for "fileExists" and "smsExists":  
  29.   if (!fileExists) {  
  30.     if (smsExists) {  
  31.       // "sms" was created for a file that no longer exists. Remove it:  
  32.       removeServerMediaSession(sms);  
  33.       sms = NULL;  
  34.     }  
  35.   
  36.     return NULL;  
  37.   } else {  
  38.     if (smsExists && isFirstLookupInSession) {   
  39.       // Remove the existing "ServerMediaSession" and create a new one, in case the underlying  
  40.       // file has changed in some way:  
  41.       removeServerMediaSession(sms);   
  42.       sms = NULL;  
  43.     }   
  44.   
  45.     if (sms == NULL) {  
  46.       sms = createNewSMS(envir(), streamName, fid);   
  47.       addServerMediaSession(sms);  
  48.     }  
  49.   
  50.     fclose(fid);  
  51.     return sms;  
  52.   }  
  53. }  
[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. static ServerMediaSession* createNewSMS(UsageEnvironment& env,  
  2.                     char const* fileName, FILE/*fid*/) {  
  3.   
  4.   ServerMediaSession* sms = NULL;  
  5.   Boolean const reuseSource = False;  
  6.   if (strcmp(fileName, "live") == 0) {  
  7.     NEW_SMS("live");  
  8.     //env << "live detected. addsubsession:\n";  
  9.     //sms->addSubsession(LiveADTSAudioServerMediaSubsession::createNew(env, fileName, reuseSource));  
  10.     OutPacketBuffer::maxSize = 300000;   
  11.     sms->addSubsession(LiveVideoFileServerMediaSubsession::createNew(env, fileName, reuseSource));  
  12.     return sms;  
  13.   }     
  14.   
  15.   // Use the file name extension to determine the type of "ServerMediaSession":  
  16.   char const* extension = strrchr(fileName, '.');  
  17.   if (extension == NULL) return NULL;  
  18.   
  19.   if (strcmp(extension, ".aac") == 0) {  
  20.     // Assumed to be an AAC Audio (ADTS format) file:  
  21.     NEW_SMS("AAC Audio");  
  22.     sms->addSubsession(ADTSAudioFileServerMediaSubsession::createNew(env, fileName, reuseSource));  
  23.   } else if (strcmp(extension, ".amr") == 0) {  
  24.     // Assumed to be an AMR Audio file:  
  25.     NEW_SMS("AMR Audio");  
  26.     sms->addSubsession(AMRAudioFileServerMediaSubsession::createNew(env, fileName, reuseSource));  
  27.   } else if (strcmp(extension, ".ac3") == 0) {  
  28.     // Assumed to be an AC-3 Audio file:  
  29.     NEW_SMS("AC-3 Audio");  
  30.     sms->addSubsession(AC3AudioFileServerMediaSubsession::createNew(env, fileName, reuseSource));  
  31.   } else if (strcmp(extension, ".m4e") == 0) {  
  32.     // Assumed to be a MPEG-4 Video Elementary Stream file:  
  33.     NEW_SMS("MPEG-4 Video");  
  34.     sms->addSubsession(MPEG4VideoFileServerMediaSubsession::createNew(env, fileName, reuseSource));  
  35.   } else if (strcmp(extension, ".264") == 0) {  
  36.     // Assumed to be a H.264 Video Elementary Stream file:  
  37.     NEW_SMS("H.264 Video");  
  38.     OutPacketBuffer::maxSize = 300000; // allow for some possibly large H.264 frames  
  39.     sms->addSubsession(H264VideoFileServerMediaSubsession::createNew(env, fileName, reuseSource));  
  40.   } else if (strcmp(extension, ".265") == 0) {  
  41.     // Assumed to be a H.265 Video Elementary Stream file:  
  42.     NEW_SMS("H.265 Video");  
  43.     OutPacketBuffer::maxSize = 300000; // allow for some possibly large H.265 frames  
  44.     sms->addSubsession(H265VideoFileServerMediaSubsession::createNew(env, fileName, reuseSource));  
  45.   } else if (strcmp(extension, ".mp3") == 0) {  
  46.     // Assumed to be a MPEG-1 or 2 Audio file:  
  47.     NEW_SMS("MPEG-1 or 2 Audio");  
  48.     // To stream using 'ADUs' rather than raw MP3 frames, uncomment the following:  
  49. //#define STREAM_USING_ADUS 1  
  50.     // To also reorder ADUs before streaming, uncomment the following:  
  51. //#define INTERLEAVE_ADUS 1  
  52.     // (For more information about ADUs and interleaving,  
  53.     //  see <http://www.live555.com/rtp-mp3/>)  
  54.     Boolean useADUs = False;  
  55.     Interleaving* interleaving = NULL;  
  56. #ifdef STREAM_USING_ADUS  
  57.     useADUs = True;  
  58. #ifdef INTERLEAVE_ADUS  
  59.     unsigned char interleaveCycle[] = {0,2,1,3}; // or choose your own...  
  60.     unsigned const interleaveCycleSize  
  61.       = (sizeof interleaveCycle)/(sizeof (unsigned char));  
  62.     interleaving = new Interleaving(interleaveCycleSize, interleaveCycle);  
  63. #endif  
  64. #endif  
  65.     sms->addSubsession(MP3AudioFileServerMediaSubsession::createNew(env, fileName, reuseSource, useADUs, interleaving));  
  66.   } else if (strcmp(extension, ".mpg") == 0) {  
  67.     // Assumed to be a MPEG-1 or 2 Program Stream (audio+video) file:  
  68.     NEW_SMS("MPEG-1 or 2 Program Stream");  
  69.     MPEG1or2FileServerDemux* demux  
  70.       = MPEG1or2FileServerDemux::createNew(env, fileName, reuseSource);  
  71.     sms->addSubsession(demux->newVideoServerMediaSubsession());  
  72.     sms->addSubsession(demux->newAudioServerMediaSubsession());  
  73.   } else if (strcmp(extension, ".vob") == 0) {  
  74.     // Assumed to be a VOB (MPEG-2 Program Stream, with AC-3 audio) file:  
  75.     NEW_SMS("VOB (MPEG-2 video with AC-3 audio)");  
  76.     MPEG1or2FileServerDemux* demux  
  77.       = MPEG1or2FileServerDemux::createNew(env, fileName, reuseSource);  
  78.     sms->addSubsession(demux->newVideoServerMediaSubsession());  
  79.     sms->addSubsession(demux->newAC3AudioServerMediaSubsession());  
  80.   } else if (strcmp(extension, ".ts") == 0) {  
  81.     // Assumed to be a MPEG Transport Stream file:  
  82.     // Use an index file name that's the same as the TS file name, except with ".tsx":  
  83.     unsigned indexFileNameLen = strlen(fileName) + 2; // allow for trailing "x\0"  
  84.     char* indexFileName = new char[indexFileNameLen];  
  85.     sprintf(indexFileName, "%sx", fileName);  
  86.     NEW_SMS("MPEG Transport Stream");  
  87.     sms->addSubsession(MPEG2TransportFileServerMediaSubsession::createNew(env, fileName, indexFileName, reuseSource));  
  88.     delete[] indexFileName;  
  89.   } else if (strcmp(extension, ".wav") == 0) {  
  90.     // Assumed to be a WAV Audio file:  
  91.     NEW_SMS("WAV Audio Stream");  
  92.     // To convert 16-bit PCM data to 8-bit u-law, prior to streaming,  
  93.     // change the following to True:  
  94.     Boolean convertToULaw = False;  
  95.     sms->addSubsession(WAVAudioFileServerMediaSubsession::createNew(env, fileName, reuseSource, convertToULaw));  
  96.   } else if (strcmp(extension, ".dv") == 0) {  
  97.     // Assumed to be a DV Video file  
  98.     // First, make sure that the RTPSinks' buffers will be large enough to handle the huge size of DV frames (as big as 288000).  
  99.     OutPacketBuffer::maxSize = 300000;  
  100.   
  101.     NEW_SMS("DV Video");  
  102.     sms->addSubsession(DVVideoFileServerMediaSubsession::createNew(env, fileName, reuseSource));  
  103.   } else if (strcmp(extension, ".mkv") == 0 || strcmp(extension, ".webm") == 0) {  
  104.     // Assumed to be a Matroska file (note that WebM ('.webm') files are also Matroska files)  
  105.     OutPacketBuffer::maxSize = 100000; // allow for some possibly large VP8 or VP9 frames  
  106.     NEW_SMS("Matroska video+audio+(optional)subtitles");  
  107.   
  108.     // Create a Matroska file server demultiplexor for the specified file.  
  109.     // (We enter the event loop to wait for this to complete.)  
  110.     MatroskaDemuxCreationState creationState;  
  111.     creationState.watchVariable = 0;  
  112.     MatroskaFileServerDemux::createNew(env, fileName, onMatroskaDemuxCreation, &creationState);  
  113.     env.taskScheduler().doEventLoop(&creationState.watchVariable);  
  114.   
  115.     ServerMediaSubsession* smss;  
  116.     while ((smss = creationState.demux->newServerMediaSubsession()) != NULL) {  
  117.       sms->addSubsession(smss);  
  118.     }  
  119.   } else if (strcmp(extension, ".ogg") == 0 || strcmp(extension, ".ogv") == 0 || strcmp(extension, ".opus") == 0) {  
  120.     // Assumed to be an Ogg file  
  121.     NEW_SMS("Ogg video and/or audio");  
  122.   
  123.     // Create a Ogg file server demultiplexor for the specified file.  
  124.     // (We enter the event loop to wait for this to complete.)  
  125.     OggDemuxCreationState creationState;  
  126.     creationState.watchVariable = 0;  
  127.     OggFileServerDemux::createNew(env, fileName, onOggDemuxCreation, &creationState);  
  128.     env.taskScheduler().doEventLoop(&creationState.watchVariable);  
  129.   
  130.     ServerMediaSubsession* smss;  
  131.     while ((smss = creationState.demux->newServerMediaSubsession()) != NULL) {  
  132.       sms->addSubsession(smss);  
  133.     }  
  134.   }  
  135.   
  136.   return sms;  
  137. }  

2、添加LiveADTSAudioServerMediaSubsession

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. #ifndef _H264_STREAM_FILE_SOURCE_HH  
  2. #define _H264_STREAM_FILE_SOURCE_HH  
  3.   
  4. #ifndef _FRAMED_FILE_SOURCE_HH  
  5. #include "FramedFileSource.hh"  
  6. #endif  
  7.   
  8. #include<pthread.h>  
  9. #include "semaphore.h"  
  10.   
  11. #define H264_BUF_SIZE 150000  
  12. #define H264_BUF_COUNT 10  
  13.   
  14. typedef void (*CB_FUN)(void);  
  15. extern void h264_buf_init();  
  16. extern void h264_buf_destroy();  
  17. extern Boolean h264_buf_full();  
  18. extern Boolean h264_buf_empty();  
  19. extern int h264_buf_put(unsigned char* buf,int len);  
  20. extern unsigned char* h264_buf_get(int* len);  
  21.   
  22. extern sem_t h264_f;  
  23. extern sem_t h264_e;  
  24. extern int b264IsInit;  
  25. extern CB_FUN startfun;  
  26. extern CB_FUN endfun;  
  27.   
  28. class LiveH264StreamSource: public FramedSource {  
  29. public:  
  30.   static LiveH264StreamSource* createNew(UsageEnvironment& env,  
  31.                      char const* fileName,  
  32.                      unsigned preferredFrameSize = 0,  
  33.                      unsigned playTimePerFrame = 0);  
  34.   // "preferredFrameSize" == 0 means 'no preference'  
  35.   // "playTimePerFrame" is in microseconds  
  36. /* 
  37.   static LiveH264StreamSource* createNew(UsageEnvironment& env, 
  38.                      unsigned preferredFrameSize = 0, 
  39.                      unsigned playTimePerFrame = 0); 
  40.       // an alternative version of "createNew()" that's used if you already have 
  41.       // an open file. 
  42. */  
  43.   u_int64_t fileSize() const { return fFileSize; }  
  44.       // 0 means zero-length, unbounded, or unknown  
  45.   
  46.   void seekToByteAbsolute(u_int64_t byteNumber, u_int64_t numBytesToStream = 0);  
  47.     // if "numBytesToStream" is >0, then we limit the stream to that number of bytes, before treating it as EOF  
  48.   void seekToByteRelative(int64_t offset, u_int64_t numBytesToStream = 0);  
  49.   void seekToEnd(); // to force EOF handling on the next read  
  50.   
  51. protected:  
  52.   LiveH264StreamSource(UsageEnvironment& env,  
  53.                unsigned preferredFrameSize,  
  54.                unsigned playTimePerFrame);  
  55.     // called only by createNew()  
  56.   
  57.   virtual ~LiveH264StreamSource();  
  58.   
  59.   static void fileReadableHandler(LiveH264StreamSource* source, int mask);  
  60.   void doReadFromFile();  
  61.   
  62. private:  
  63.   // redefined virtual functions:  
  64.   virtual void doGetNextFrame();  
  65.   virtual void doStopGettingFrames();  
  66.   
  67. protected:  
  68.   u_int64_t fFileSize;  
  69.   
  70. private:  
  71.   unsigned fPreferredFrameSize;  
  72.   unsigned fPlayTimePerFrame;  
  73.   Boolean fFidIsSeekable;  
  74.   unsigned fLastPlayTime;  
  75.   Boolean fHaveStartedReading;  
  76.   Boolean fLimitNumBytesToStream;  
  77.   u_int64_t fNumBytesToStream; // used iff "fLimitNumBytesToStream" is True  
  78. };  
  79.   
  80. #endif  


[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. #include "LiveADTSAudioServerMediaSubsession.hh"  
  2. #include "LiveADTSAudioSource.hh"  
  3. #include "MPEG4GenericRTPSink.hh"  
  4.   
  5. LiveADTSAudioServerMediaSubsession*  
  6. LiveADTSAudioServerMediaSubsession::createNew(UsageEnvironment& env,  
  7.                          char const* fileName,  
  8.                          Boolean reuseFirstSource) {  
  9.   return new LiveADTSAudioServerMediaSubsession(env, fileName, reuseFirstSource);  
  10. }  
  11.   
  12. LiveADTSAudioServerMediaSubsession  
  13. ::LiveADTSAudioServerMediaSubsession(UsageEnvironment& env,  
  14.                     char const* fileName, Boolean reuseFirstSource)  
  15.   : FileServerMediaSubsession(env, fileName, reuseFirstSource) {  
  16. }  
  17.   
  18. LiveADTSAudioServerMediaSubsession  
  19. ::~LiveADTSAudioServerMediaSubsession() {  
  20. }  
  21.   
  22. FramedSource* LiveADTSAudioServerMediaSubsession  
  23. ::createNewStreamSource(unsigned /*clientSessionId*/, unsigned& estBitrate) {  
  24.   estBitrate = 96; // kbps, estimate  
  25.   
  26.   return LiveADTSAudioSource::createNew(envir());  
  27. }  
  28.   
  29. RTPSink* LiveADTSAudioServerMediaSubsession  
  30. ::createNewRTPSink(Groupsock* rtpGroupsock,  
  31.            unsigned char rtpPayloadTypeIfDynamic,  
  32.            FramedSource* inputSource) {  
  33.   LiveADTSAudioSource* adtsSource = (LiveADTSAudioSource*)inputSource;  
  34.   return MPEG4GenericRTPSink::createNew(envir(), rtpGroupsock,  
  35.                     rtpPayloadTypeIfDynamic,  
  36.                     adtsSource->samplingFrequency(),  
  37.                     "audio""AAC-hbr", adtsSource->configStr(),  
  38.                     adtsSource->numChannels());  
  39. }  

3、添加LiveADTSAudioSource类

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. #ifndef _LiveADTSAudioSource_HH  
  2. #define _LiveADTSAudioSource_HH  
  3.   
  4. #ifndef _FRAMED_FILE_SOURCE_HH  
  5. #include "FramedFileSource.hh"  
  6. #endif  
  7.   
  8. #include<pthread.h>  
  9. #include "semaphore.h"  
  10.   
  11. #define AAC_BUF_SIZE 10000  
  12. #define AAC_BUF_COUNT 20  
  13.   
  14. extern void aac_buf_init();  
  15. extern Boolean aac_buf_full();  
  16. extern Boolean aac_buf_empty();  
  17. extern int aac_buf_put(unsigned char* buf,int len);  
  18. extern unsigned char* aac_buf_get();  
  19. extern void aac_buf_destroy();  
  20.   
  21. extern sem_t aac_f;  
  22. extern sem_t aac_e;  
  23. extern int bIsInit;  
  24.   
  25. class LiveADTSAudioSource: public FramedSource {  
  26. public:  
  27.   static LiveADTSAudioSource* createNew(UsageEnvironment& env);  
  28.   
  29.   unsigned samplingFrequency() const { return fSamplingFrequency; }  
  30.   unsigned numChannels() const { return fNumChannels; }  
  31.   char const* configStr() const { return fConfigStr; }  
  32.       // returns the 'AudioSpecificConfig' for this stream (in ASCII form)  
  33.   
  34. private:  
  35.   LiveADTSAudioSource(UsageEnvironment& env, u_int8_t profile,  
  36.               u_int8_t samplingFrequencyIndex, u_int8_t channelConfiguration);  
  37.     // called only by createNew()  
  38.   
  39.   virtual ~LiveADTSAudioSource();  
  40.   
  41. private:  
  42.   // redefined virtual functions:  
  43.   virtual void doGetNextFrame();  
  44.   
  45. private:  
  46.   unsigned fSamplingFrequency;  
  47.   unsigned fNumChannels;  
  48.   unsigned fuSecsPerFrame;  
  49.   char fConfigStr[5];  
  50. };  
  51.   
  52. #endif  

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. #include "LiveADTSAudioSource.hh"  
  2. #include "InputFile.hh"  
  3. #include <GroupsockHelper.hh>  
  4.   
  5. // ADTSAudioFileSource //  
  6.   
  7. static unsigned const samplingFrequencyTable[16] = {  
  8.   96000, 88200, 64000, 48000,  
  9.   44100, 32000, 24000, 22050,  
  10.   16000, 12000, 11025, 8000,  
  11.   7350, 0, 0, 0  
  12. };  
  13.   
  14. unsigned char aac_framebuf[AAC_BUF_COUNT][AAC_BUF_SIZE];  
  15. int aac_frame_len[AAC_BUF_COUNT];  
  16. int aac_buf_head;  
  17. int aac_buf_tail;  
  18. int aac_buf_size;  
  19.   
  20. void aac_buf_init();  
  21. void aac_buf_destroy();  
  22. Boolean aac_buf_full();  
  23. Boolean aac_buf_empty();  
  24. int aac_buf_put(unsigned char* buf,int len);  
  25. unsigned char* aac_buf_get();  
  26.   
  27. sem_t aac_f;  
  28. sem_t aac_e;  
  29. sem_t aac_m;  
  30. int bIsInit = 0;  
  31. void aac_buf_init()  
  32. {  
  33.     if(bIsInit == 0)  
  34.     {         
  35.         sem_init(&aac_f,0,0);  
  36.             sem_init(&aac_e,0,AAC_BUF_COUNT);  
  37.             sem_init(&aac_m,0,1);  
  38.         aac_buf_head = 0;  
  39.         aac_buf_tail = 0;  
  40.         aac_buf_size = 0;  
  41.     }  
  42. }  
  43. Boolean aac_buf_full()  
  44. {  
  45.     if(aac_buf_size == AAC_BUF_COUNT)  
  46.         return True;  
  47.     return False;  
  48. }  
  49. Boolean aac_buf_empty()  
  50. {  
  51.     if(aac_buf_size == 0)  
  52.         return True;  
  53.     return False;  
  54. }  
  55. int aac_buf_put(unsigned char* buf,int len)  
  56. {  
  57.     sem_wait(&aac_e);  
  58.     sem_wait(&aac_m);  
  59.     bzero(aac_framebuf[aac_buf_tail],AAC_BUF_SIZE);  
  60.     memcpy(aac_framebuf[aac_buf_tail],buf,len);  
  61.     aac_frame_len[aac_buf_tail] = len;  
  62.     aac_buf_tail = (aac_buf_tail + 1)%AAC_BUF_COUNT;  
  63.     aac_buf_size++;  
  64.     sem_post(&aac_m);  
  65.     sem_post(&aac_f);  
  66. }  
  67. unsigned char* aac_buf_get()  
  68. {  
  69.     sem_wait(&aac_m);  
  70.     unsigned char* rt = aac_framebuf[aac_buf_head];  
  71.     aac_buf_head = (aac_buf_head+1)%AAC_BUF_COUNT;  
  72.     aac_buf_size--;   
  73.     sem_post(&aac_m);  
  74.   
  75.     return rt;  
  76. }  
  77.   
  78. void aac_buf_destroy()  
  79. {  
  80.     sem_destroy(&aac_f);  
  81.     sem_destroy(&aac_e);  
  82.     sem_destroy(&aac_m);  
  83. }  
  84.   
  85. LiveADTSAudioSource*  
  86. LiveADTSAudioSource::createNew(UsageEnvironment& env) {  
  87.       
  88.     aac_buf_init();  
  89.     bIsInit = 1;  
  90.   
  91.     return new LiveADTSAudioSource(env, 1, 4, 2);  
  92. }  
  93.   
  94. LiveADTSAudioSource  
  95. ::LiveADTSAudioSource(UsageEnvironment& env, u_int8_t profile,  
  96.               u_int8_t samplingFrequencyIndex, u_int8_t channelConfiguration)  
  97.   : FramedSource(env) {   
  98.   fSamplingFrequency = samplingFrequencyTable[samplingFrequencyIndex];  
  99.   fNumChannels = channelConfiguration == 0 ? 2 : channelConfiguration;  
  100.   fuSecsPerFrame  
  101.     = (1024/*samples-per-frame*/*1000000) / fSamplingFrequency/*samples-per-second*/;  
  102.   
  103.   // Construct the 'AudioSpecificConfig', and from it, the corresponding ASCII string:  
  104.   unsigned char audioSpecificConfig[2];  
  105.   u_int8_t const audioObjectType = profile + 1;  
  106.   audioSpecificConfig[0] = (audioObjectType<<3) | (samplingFrequencyIndex>>1);  
  107.   audioSpecificConfig[1] = (samplingFrequencyIndex<<7) | (channelConfiguration<<3);  
  108.   sprintf(fConfigStr, "%02X%02x", audioSpecificConfig[0], audioSpecificConfig[1]);  
  109.   //env << "liveADTSAudioSource : construct\n";  
  110. }  
  111.   
  112. LiveADTSAudioSource::~LiveADTSAudioSource() {  
  113.   
  114. }  
  115.   
  116. // Note: We should change the following to use asynchronous file reading, #####  
  117. // as we now do with ByteStreamFileSource. #####  
  118. void LiveADTSAudioSource::doGetNextFrame() {  
  119.   // Begin by reading the 7-byte fixed_variable headers:  
  120.   sem_wait(&aac_f);  
  121.   
  122.   unsigned char* cur = aac_buf_get();  
  123.   int pos = 0;  
  124.   unsigned char* headers;  
  125.   headers = cur;  
  126.   
  127.   // Extract important fields from the headers:  
  128.   Boolean protection_absent = headers[1]&0x01;  
  129.   
  130.   u_int16_t frame_length  
  131.     = ((headers[3]&0x03)<<11) | (headers[4]<<3) | ((headers[5]&0xE0)>>5);  
  132. if(0)  
  133. {  
  134.   u_int16_t syncword = (headers[0]<<4) | (headers[1]>>4);  
  135.   fprintf(stderr, "Read frame: syncword 0x%x, protection_absent %d, frame_length %d\n", syncword, protection_absent, frame_length);  
  136.   if (syncword != 0xFFF) fprintf(stderr, "WARNING: Bad syncword!\n");  
  137. }  
  138.   unsigned numBytesToRead  
  139.     = frame_length > 7 ? frame_length - 7 : 0;  
  140.   
  141.   pos = 7;  
  142.   // If there's a 'crc_check' field, skip it:  
  143.   if (!protection_absent) {  
  144.     pos += 2;  
  145.     numBytesToRead = numBytesToRead > 2 ? numBytesToRead - 2 : 0;  
  146.   }  
  147.   
  148.   // Next, read the raw frame data into the buffer provided:  
  149.   if (numBytesToRead > fMaxSize) {  
  150.     fNumTruncatedBytes = numBytesToRead - fMaxSize;  
  151.     numBytesToRead = fMaxSize;  
  152.   }  
  153.   
  154.   memcpy(fTo,cur + pos,numBytesToRead);  
  155.   sem_post(&aac_e);  
  156.   
  157.   int numBytesRead = numBytesToRead;  
  158.   fFrameSize = numBytesRead;  
  159.   fNumTruncatedBytes += numBytesToRead - numBytesRead;  
  160.   
  161.   // Set the 'presentation time':  
  162.   if (fPresentationTime.tv_sec == 0 && fPresentationTime.tv_usec == 0) {  
  163.     // This is the first frame, so use the current time:  
  164.     gettimeofday(&fPresentationTime, NULL);  
  165.   } else {  
  166.     // Increment by the play time of the previous frame:  
  167.     unsigned uSeconds = fPresentationTime.tv_usec + fuSecsPerFrame;  
  168.     fPresentationTime.tv_sec += uSeconds/1000000;  
  169.     fPresentationTime.tv_usec = uSeconds%1000000;  
  170.   }  
  171.   
  172.   fDurationInMicroseconds = fuSecsPerFrame;  
  173.   
  174.   // Switch to another task, and inform the reader that he has data:  
  175.   nextTask() = envir().taskScheduler().scheduleDelayedTask(0,  
  176.                 (TaskFunc*)FramedSource::afterGetting, this);  
  177. }  

4、添加LiveVideoFileServerMediaSubsession类

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. #ifndef _LIVE_VIDEO_FILE_SERVER_MEDIA_SUBSESSION_HH  
  2. #define _LIVE_VIDEO_FILE_SERVER_MEDIA_SUBSESSION_HH  
  3.   
  4. #ifndef _FILE_SERVER_MEDIA_SUBSESSION_HH  
  5. #include "FileServerMediaSubsession.hh"  
  6. #endif  
  7.   
  8. class LiveVideoFileServerMediaSubsession: public FileServerMediaSubsession {  
  9. public:  
  10.   static LiveVideoFileServerMediaSubsession*  
  11.   createNew(UsageEnvironment& env, char const* fileName, Boolean reuseFirstSource);  
  12.   
  13.   // Used to implement "getAuxSDPLine()":  
  14.   void checkForAuxSDPLine1();  
  15.   void afterPlayingDummy1();  
  16.   
  17. protected:  
  18.   LiveVideoFileServerMediaSubsession(UsageEnvironment& env,  
  19.                       char const* fileName, Boolean reuseFirstSource);  
  20.       // called only by createNew();  
  21.   virtual ~LiveVideoFileServerMediaSubsession();  
  22.   
  23.   void setDoneFlag() { fDoneFlag = ~0; }  
  24.   
  25. protected// redefined virtual functions  
  26.   virtual char const* getAuxSDPLine(RTPSink* rtpSink,  
  27.                     FramedSource* inputSource);  
  28.   virtual FramedSource* createNewStreamSource(unsigned clientSessionId,  
  29.                           unsigned& estBitrate);  
  30.   virtual RTPSink* createNewRTPSink(Groupsock* rtpGroupsock,  
  31.                                     unsigned char rtpPayloadTypeIfDynamic,  
  32.                     FramedSource* inputSource);  
  33.   
  34. private:  
  35.   char* fAuxSDPLine;  
  36.   char fDoneFlag; // used when setting up "fAuxSDPLine"  
  37.   RTPSink* fDummyRTPSink; // ditto  
  38. };  
  39.   
  40. #endif  

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. #include "LiveVideoFileServerMediaSubsession.hh"  
  2. #include "H264VideoRTPSink.hh"  
  3. #include "LiveH264StreamSource.hh"  
  4. #include "H264VideoStreamFramer.hh"  
  5.   
  6. LiveVideoFileServerMediaSubsession*  
  7. LiveVideoFileServerMediaSubsession::createNew(UsageEnvironment& env,  
  8.                           char const* fileName,  
  9.                           Boolean reuseFirstSource) {  
  10.   return new LiveVideoFileServerMediaSubsession(env, fileName, reuseFirstSource);  
  11. }  
  12.   
  13. LiveVideoFileServerMediaSubsession::LiveVideoFileServerMediaSubsession(UsageEnvironment& env,  
  14.                                        char const* fileName, Boolean reuseFirstSource)  
  15.   : FileServerMediaSubsession(env, fileName, reuseFirstSource),  
  16.     fAuxSDPLine(NULL), fDoneFlag(0), fDummyRTPSink(NULL) {  
  17. }  
  18.   
  19. LiveVideoFileServerMediaSubsession::~LiveVideoFileServerMediaSubsession() {  
  20.   delete[] fAuxSDPLine;  
  21. }  
  22.   
  23. static void afterPlayingDummy(void* clientData) {  
  24.   LiveVideoFileServerMediaSubsession* subsess = (LiveVideoFileServerMediaSubsession*)clientData;  
  25.   subsess->afterPlayingDummy1();  
  26. }  
  27.   
  28. void LiveVideoFileServerMediaSubsession::afterPlayingDummy1() {  
  29.   // Unschedule any pending 'checking' task:  
  30.   envir().taskScheduler().unscheduleDelayedTask(nextTask());  
  31.   // Signal the event loop that we're done:  
  32.   setDoneFlag();  
  33. }  
  34.   
  35. static void checkForAuxSDPLine(void* clientData) {  
  36.   LiveVideoFileServerMediaSubsession* subsess = (LiveVideoFileServerMediaSubsession*)clientData;  
  37.   subsess->checkForAuxSDPLine1();  
  38. }  
  39.   
  40. void LiveVideoFileServerMediaSubsession::checkForAuxSDPLine1() {  
  41.   char const* dasl;  
  42.   
  43.   if (fAuxSDPLine != NULL) {  
  44.     // Signal the event loop that we're done:  
  45.     setDoneFlag();  
  46.   } else if (fDummyRTPSink != NULL && (dasl = fDummyRTPSink->auxSDPLine()) != NULL) {  
  47.     fAuxSDPLine = strDup(dasl);  
  48.     fDummyRTPSink = NULL;  
  49.   
  50.     // Signal the event loop that we're done:  
  51.     setDoneFlag();  
  52.   } else if (!fDoneFlag) {  
  53.     // try again after a brief delay:  
  54.     int uSecsToDelay = 100000; // 100 ms  
  55.     nextTask() = envir().taskScheduler().scheduleDelayedTask(uSecsToDelay,  
  56.                   (TaskFunc*)checkForAuxSDPLine, this);  
  57.   }  
  58. }  
  59.   
  60. char const* LiveVideoFileServerMediaSubsession::getAuxSDPLine(RTPSink* rtpSink, FramedSource* inputSource) {  
  61.   if (fAuxSDPLine != NULL) return fAuxSDPLine; // it's already been set up (for a previous client)  
  62.   
  63.   if (fDummyRTPSink == NULL) { // we're not already setting it up for another, concurrent stream  
  64.     // Note: For H264 video files, the 'config' information ("profile-level-id" and "sprop-parameter-sets") isn't known  
  65.     // until we start reading the file.  This means that "rtpSink"s "auxSDPLine()" will be NULL initially,  
  66.     // and we need to start reading data from our file until this changes.  
  67.     fDummyRTPSink = rtpSink;  
  68.   
  69.     // Start reading the file:  
  70.     fDummyRTPSink->startPlaying(*inputSource, afterPlayingDummy, this);  
  71.   
  72.     // Check whether the sink's 'auxSDPLine()' is ready:  
  73.     checkForAuxSDPLine(this);  
  74.   }  
  75.   
  76.   envir().taskScheduler().doEventLoop(&fDoneFlag);  
  77.   
  78.   return fAuxSDPLine;  
  79. }  
  80.   
  81. FramedSource* LiveVideoFileServerMediaSubsession::createNewStreamSource(unsigned /*clientSessionId*/, unsigned& estBitrate) {  
  82.   estBitrate = 500; // kbps, estimate  
  83.   
  84.   // Create the video source:  
  85.   LiveH264StreamSource* fileSource = LiveH264StreamSource::createNew(envir(), fFileName);  
  86.   if (fileSource == NULL) return NULL;  
  87.   fFileSize = fileSource->fileSize();  
  88.   
  89.   // Create a framer for the Video Elementary Stream:  
  90.   return H264VideoStreamFramer::createNew(envir(), fileSource);  
  91. }  
  92.   
  93. RTPSink* LiveVideoFileServerMediaSubsession  
  94. ::createNewRTPSink(Groupsock* rtpGroupsock,  
  95.            unsigned char rtpPayloadTypeIfDynamic,  
  96.            FramedSource* /*inputSource*/) {  
  97.   return H264VideoRTPSink::createNew(envir(), rtpGroupsock, rtpPayloadTypeIfDynamic);  
  98. }  

5、添加LiveH264StreamSource类

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. #ifndef _H264_STREAM_FILE_SOURCE_HH  
  2. #define _H264_STREAM_FILE_SOURCE_HH  
  3.   
  4. #ifndef _FRAMED_FILE_SOURCE_HH  
  5. #include "FramedFileSource.hh"  
  6. #endif  
  7.   
  8. #include<pthread.h>  
  9. #include "semaphore.h"  
  10.   
  11. #define H264_BUF_SIZE 150000  
  12. #define H264_BUF_COUNT 10  
  13.   
  14. typedef void (*CB_FUN)(void);  
  15. extern void h264_buf_init();  
  16. extern void h264_buf_destroy();  
  17. extern Boolean h264_buf_full();  
  18. extern Boolean h264_buf_empty();  
  19. extern int h264_buf_put(unsigned char* buf,int len);  
  20. extern unsigned char* h264_buf_get(int* len);  
  21.   
  22. extern sem_t h264_f;  
  23. extern sem_t h264_e;  
  24. extern int b264IsInit;  
  25. extern CB_FUN startfun;  
  26. extern CB_FUN endfun;  
  27.   
  28. class LiveH264StreamSource: public FramedSource {  
  29. public:  
  30.   static LiveH264StreamSource* createNew(UsageEnvironment& env,  
  31.                      char const* fileName,  
  32.                      unsigned preferredFrameSize = 0,  
  33.                      unsigned playTimePerFrame = 0);  
  34.   // "preferredFrameSize" == 0 means 'no preference'  
  35.   // "playTimePerFrame" is in microseconds  
  36. /* 
  37.   static LiveH264StreamSource* createNew(UsageEnvironment& env, 
  38.                      unsigned preferredFrameSize = 0, 
  39.                      unsigned playTimePerFrame = 0); 
  40.       // an alternative version of "createNew()" that's used if you already have 
  41.       // an open file. 
  42. */  
  43.   u_int64_t fileSize() const { return fFileSize; }  
  44.       // 0 means zero-length, unbounded, or unknown  
  45.   
  46.   void seekToByteAbsolute(u_int64_t byteNumber, u_int64_t numBytesToStream = 0);  
  47.     // if "numBytesToStream" is >0, then we limit the stream to that number of bytes, before treating it as EOF  
  48.   void seekToByteRelative(int64_t offset, u_int64_t numBytesToStream = 0);  
  49.   void seekToEnd(); // to force EOF handling on the next read  
  50.   
  51. protected:  
  52.   LiveH264StreamSource(UsageEnvironment& env,  
  53.                unsigned preferredFrameSize,  
  54.                unsigned playTimePerFrame);  
  55.     // called only by createNew()  
  56.   
  57.   virtual ~LiveH264StreamSource();  
  58.   
  59.   static void fileReadableHandler(LiveH264StreamSource* source, int mask);  
  60.   void doReadFromFile();  
  61.   
  62. private:  
  63.   // redefined virtual functions:  
  64.   virtual void doGetNextFrame();  
  65.   virtual void doStopGettingFrames();  
  66.   
  67. protected:  
  68.   u_int64_t fFileSize;  
  69.   
  70. private:  
  71.   unsigned fPreferredFrameSize;  
  72.   unsigned fPlayTimePerFrame;  
  73.   Boolean fFidIsSeekable;  
  74.   unsigned fLastPlayTime;  
  75.   Boolean fHaveStartedReading;  
  76.   Boolean fLimitNumBytesToStream;  
  77.   u_int64_t fNumBytesToStream; // used iff "fLimitNumBytesToStream" is True  
  78. };  
  79.   
  80. #endif  

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. #include "LiveH264StreamSource.hh"  
  2. #include "InputFile.hh"  
  3. #include "GroupsockHelper.hh"  
  4.   
  5. // LiveH264StreamSource //  
  6. unsigned char h264_framebuf[H264_BUF_COUNT][H264_BUF_SIZE];  
  7. int h264_frame_len[H264_BUF_COUNT];  
  8. int h264_buf_head;  
  9. int h264_buf_tail;  
  10. int h264_buf_size;  
  11.   
  12. void h264_buf_init();  
  13. void h264_buf_destroy();  
  14. Boolean h264_buf_full();  
  15. Boolean h264_buf_empty();  
  16. int h264_buf_put(unsigned char* buf,int len);  
  17. unsigned char* h264_buf_get();  
  18.   
  19. sem_t h264_f;  
  20. sem_t h264_e;  
  21. sem_t h264_m;  
  22. int b264IsInit = 0;  
  23. CB_FUN startfun = NULL;  
  24. CB_FUN endfun = NULL;  
  25.   
  26. unsigned char obuf[H264_BUF_SIZE];  
  27. unsigned olen = 0;  
  28.   
  29. void h264_buf_init()  
  30. {  
  31.     if(b264IsInit == 0)  
  32.     {         
  33.         sem_init(&h264_f,1,0);  
  34.             sem_init(&h264_e,1,H264_BUF_COUNT);  
  35.             sem_init(&h264_m,1,1);  
  36.         h264_buf_head = 0;  
  37.         h264_buf_tail = 0;  
  38.         h264_buf_size = 0;  
  39.           
  40.         //printf("must 1\n");  
  41.     }  
  42.   
  43. }  
  44. Boolean h264_buf_full()  
  45. {  
  46.     if(h264_buf_size == H264_BUF_COUNT)  
  47.         return True;  
  48.     return False;  
  49. }  
  50. Boolean h264_buf_empty()  
  51. {  
  52.     if(h264_buf_size == 0)  
  53.         return True;  
  54.     return False;  
  55. }  
  56. int h264_buf_put(unsigned char* buf,int len)  
  57. {  
  58.     sem_wait(&h264_e);  
  59.     sem_wait(&h264_m);  
  60.     bzero(h264_framebuf[h264_buf_tail],H264_BUF_SIZE);  
  61.     memcpy(h264_framebuf[h264_buf_tail],buf,len);  
  62.     h264_frame_len[h264_buf_tail] = len;  
  63.       
  64.     h264_buf_tail = (h264_buf_tail + 1)%H264_BUF_COUNT;  
  65.     h264_buf_size++;  
  66.     sem_post(&h264_f);  
  67.     sem_post(&h264_m);  
  68. }  
  69. unsigned char* h264_buf_get(int* len)  
  70. {  
  71.     sem_wait(&h264_m);  
  72.     unsigned char* rt = h264_framebuf[h264_buf_head];  
  73.     *len = h264_frame_len[h264_buf_head];  
  74.       
  75.     h264_buf_head = (h264_buf_head+1)%H264_BUF_COUNT;  
  76.     h264_buf_size--;      
  77.     sem_post(&h264_m);  
  78.   
  79.     return rt;  
  80. }  
  81.   
  82. void h264_buf_destroy()  
  83. {  
  84.     sem_destroy(&h264_f);  
  85.     sem_destroy(&h264_e);  
  86.     sem_destroy(&h264_m);  
  87. }  
  88.   
  89.   
  90. LiveH264StreamSource*  
  91. LiveH264StreamSource::createNew(UsageEnvironment& env, char const* fileName,  
  92.                 unsigned preferredFrameSize,  
  93.                 unsigned playTimePerFrame) {  
  94.   
  95.     h264_buf_init();  
  96.   
  97.     b264IsInit = 1;  
  98.   LiveH264StreamSource* newSource  
  99.     = new LiveH264StreamSource(env, preferredFrameSize, playTimePerFrame);  
  100.   
  101.     if(startfun != NULL)  
  102.     {  
  103.         startfun();  
  104.     }  
  105.      
  106.   return newSource;  
  107. }  
  108. /* 
  109. LiveH264StreamSource* 
  110. LiveH264StreamSource::createNew(UsageEnvironment& env,  
  111.                 unsigned preferredFrameSize, 
  112.                 unsigned playTimePerFrame) { 
  113.  
  114.   LiveH264StreamSource* newSource = new LiveH264StreamSource(env, preferredFrameSize, playTimePerFrame); 
  115.  
  116.   return newSource; 
  117. } 
  118. */  
  119.   
  120. void LiveH264StreamSource::seekToByteAbsolute(u_int64_t byteNumber, u_int64_t numBytesToStream) {  
  121.   fNumBytesToStream = numBytesToStream;  
  122.   fLimitNumBytesToStream = fNumBytesToStream > 0;  
  123. }  
  124.   
  125. void LiveH264StreamSource::seekToByteRelative(int64_t offset, u_int64_t numBytesToStream) {  
  126.   fNumBytesToStream = numBytesToStream;  
  127.   fLimitNumBytesToStream = fNumBytesToStream > 0;  
  128. }  
  129.   
  130. void LiveH264StreamSource::seekToEnd() {  
  131.   
  132. }  
  133.   
  134. LiveH264StreamSource::LiveH264StreamSource(UsageEnvironment& env,   
  135.                        unsigned preferredFrameSize,  
  136.                        unsigned playTimePerFrame)  
  137.   : FramedSource(env), fFileSize(0), fPreferredFrameSize(preferredFrameSize),  
  138.     fPlayTimePerFrame(playTimePerFrame), fLastPlayTime(0),  
  139.     fHaveStartedReading(False), fLimitNumBytesToStream(False), fNumBytesToStream(0) {  
  140.   
  141.   // Test whether the file is seekable  
  142.   fFidIsSeekable = False;  
  143. }  
  144.   
  145. LiveH264StreamSource::~LiveH264StreamSource() {  
  146.   
  147.   
  148.    if(endfun != NULL)  
  149.    {  
  150.     endfun();  
  151.    }  
  152. }  
  153.   
  154. void LiveH264StreamSource::doGetNextFrame() {  
  155.   
  156.   
  157.   doReadFromFile();  
  158.   
  159. }  
  160.   
  161. void LiveH264StreamSource::doStopGettingFrames() {  
  162.   //envir().taskScheduler().unscheduleDelayedTask(nextTask());  
  163. }  
  164.   
  165. void LiveH264StreamSource::fileReadableHandler(LiveH264StreamSource* source, int /*mask*/) {  
  166.   if (!source->isCurrentlyAwaitingData()) {  
  167.     source->doStopGettingFrames(); // we're not ready for the data yet  
  168.     return;  
  169.   }  
  170.   source->doReadFromFile();  
  171. }  
  172.   
  173. void LiveH264StreamSource::doReadFromFile() {  
  174.   // Try to read as many bytes as will fit in the buffer provided (or "fPreferredFrameSize" if less)  
  175.   if (fLimitNumBytesToStream && fNumBytesToStream < (u_int64_t)fMaxSize) {  
  176.     fMaxSize = (unsigned)fNumBytesToStream;  
  177.   }  
  178.   if (fPreferredFrameSize > 0 && fPreferredFrameSize < fMaxSize) {  
  179.     fMaxSize = fPreferredFrameSize;  
  180.   }  
  181.   
  182.   sem_wait(&h264_f);  
  183.   int len = 0;  
  184.   unsigned char* frame = h264_buf_get(&len);  
  185.     
  186.   if(olen > 0)  
  187.   {  
  188.     memcpy(fTo,obuf,olen);  
  189.   }  
  190.     
  191.   if(len + olen>= fMaxSize)  
  192.   {  
  193.     unsigned need = fMaxSize-olen;  
  194.     memcpy(&fTo[olen],frame,need);  
  195.       
  196.     fFrameSize = fMaxSize;    
  197.     olen = len - need;  
  198.     memcpy(obuf,&frame[need],olen);       
  199.       
  200.       
  201.   }else{  
  202.     memcpy(&fTo[olen],frame,len+ olen);   
  203.     fFrameSize = olen + len;  
  204.       
  205.     olen = 0;     
  206.   }    
  207.   sem_post(&h264_e);  
  208.    
  209.   //fFrameSize = fread(fTo, 1, fMaxSize, fFid);  
  210.   //fwrite(fTo,fFrameSize,1,file);  
  211.     
  212.     
  213.   
  214.   if (fFrameSize == 0) {  
  215.     //handleClosure();  
  216.     //return;  
  217.   }  
  218.   fNumBytesToStream -= fFrameSize;  
  219.   
  220.   // Set the 'presentation time':  
  221.   if (fPlayTimePerFrame > 0 && fPreferredFrameSize > 0) {  
  222.     if (fPresentationTime.tv_sec == 0 && fPresentationTime.tv_usec == 0) {  
  223.       // This is the first frame, so use the current time:  
  224.       gettimeofday(&fPresentationTime, NULL);  
  225.     } else {  
  226.       // Increment by the play time of the previous data:  
  227.       unsigned uSeconds = fPresentationTime.tv_usec + fLastPlayTime;  
  228.       fPresentationTime.tv_sec += uSeconds/1000000;  
  229.       fPresentationTime.tv_usec = uSeconds%1000000;  
  230.     }  
  231.   
  232.     // Remember the play time of this data:  
  233.     fLastPlayTime = (fPlayTimePerFrame*fFrameSize)/fPreferredFrameSize;  
  234.     fDurationInMicroseconds = fLastPlayTime;  
  235.   } else {  
  236.     // We don't know a specific play time duration for this data,  
  237.     // so just record the current time as being the 'presentation time':  
  238.     gettimeofday(&fPresentationTime, NULL);  
  239.   }  
  240.   
  241.   // To avoid possible infinite recursion, we need to return to the event loop to do this:  
  242.   nextTask() = envir().taskScheduler().scheduleDelayedTask(0,  
  243.                 (TaskFunc*)FramedSource::afterGetting, this);  
  244. }  

6、修改livemedia.hh,添加

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <span style="color:#666666;">#include "LiveADTSAudioSource.hh"  
  2. #include "LiveADTSAudioServerMediaSubsession.hh"  
  3. #include "LiveVideoFileServerMediaSubsession.hh"  
  4. #include "LiveH264StreamSource.hh"</span>  

7、添加接口代码

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. #include <BasicUsageEnvironment.hh>  
  2. #include "DynamicRTSPServer.hh"  
  3. #include <liveMedia.hh>  
  4. #include "version.hh"  
  5.   
  6. typedef void (*CB_FUN)(void);  
  7.   
  8. int Rtsp_Server_Start();  
  9. int Rtsp_Server_Stop();  
  10. int Rtsp_AAC_Frame(unsigned char* frame,int framelen);  
  11. int Rtsp_H264_Frame(unsigned char* frame,int framelen);  
  12. int Rtsp_Regist_Start_Routine(CB_FUN fun);  
  13. int Rtsp_Regist_Stop_Routine(CB_FUN fun);  
  14. int Rtsp_Port();  

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. #include "librtspserv.hh"  
  2. #include <pthread.h>  
  3.   
  4. pthread_t id;  
  5.   
  6. void* server_start(void* arg) {  
  7.   // Begin by setting up our usage environment:  
  8.   TaskScheduler* scheduler = BasicTaskScheduler::createNew();  
  9.   UsageEnvironment* env = BasicUsageEnvironment::createNew(*scheduler);  
  10.   
  11.   UserAuthenticationDatabase* authDB = NULL;  
  12. #ifdef ACCESS_CONTROL  
  13.   // To implement client access control to the RTSP server, do the following:  
  14.   authDB = new UserAuthenticationDatabase;  
  15.   authDB->addUserRecord("username1""password1"); // replace these with real strings  
  16.   // Repeat the above with each <username>, <password> that you wish to allow  
  17.   // access to the server.  
  18. #endif  
  19.   
  20.   // Create the RTSP server.  Try first with the default port number (554),  
  21.   // and then with the alternative port number (8554):  
  22.   RTSPServer* rtspServer;  
  23.   portNumBits rtspServerPortNum = 554;  
  24.   rtspServer = DynamicRTSPServer::createNew(*env, rtspServerPortNum, authDB);  
  25.   if (rtspServer == NULL) {  
  26.     rtspServerPortNum = 8554;  
  27.     rtspServer = DynamicRTSPServer::createNew(*env, rtspServerPortNum, authDB);  
  28.   }  
  29.   if (rtspServer == NULL) {  
  30.     *env << "Failed to create RTSP server: " << env->getResultMsg() << "\n";  
  31.     exit(1);  
  32.   }  
  33.   
  34.   *env << "LIVE555 Media Server\n";  
  35.   *env << "\tversion " << MEDIA_SERVER_VERSION_STRING  
  36.        << " (LIVE555 Streaming Media library version "  
  37.        << LIVEMEDIA_LIBRARY_VERSION_STRING << ").\n";  
  38.   
  39.   char* urlPrefix = rtspServer->rtspURLPrefix();  
  40.   *env << "Play streams from this server using the URL\n\t"  
  41.        << urlPrefix << "<filename>\nwhere <filename> is a file present in the current directory.\n";  
  42.   *env << "Each file's type is inferred from its name suffix:\n";  
  43.   *env << "\t\".264\" => a H.264 Video Elementary Stream file\n";  
  44.   *env << "\t\".265\" => a H.265 Video Elementary Stream file\n";  
  45.   *env << "\t\".aac\" => an AAC Audio (ADTS format) file\n";  
  46.   *env << "\t\".ac3\" => an AC-3 Audio file\n";  
  47.   *env << "\t\".amr\" => an AMR Audio file\n";  
  48.   *env << "\t\".dv\" => a DV Video file\n";  
  49.   *env << "\t\".m4e\" => a MPEG-4 Video Elementary Stream file\n";  
  50.   *env << "\t\".mkv\" => a Matroska audio+video+(optional)subtitles file\n";  
  51.   *env << "\t\".mp3\" => a MPEG-1 or 2 Audio file\n";  
  52.   *env << "\t\".mpg\" => a MPEG-1 or 2 Program Stream (audio+video) file\n";  
  53.   *env << "\t\".ogg\" or \".ogv\" or \".opus\" => an Ogg audio and/or video file\n";  
  54.   *env << "\t\".ts\" => a MPEG Transport Stream file\n";  
  55.   *env << "\t\t(a \".tsx\" index file - if present - provides server 'trick play' support)\n";  
  56.   *env << "\t\".vob\" => a VOB (MPEG-2 video with AC-3 audio) file\n";  
  57.   *env << "\t\".wav\" => a WAV Audio file\n";  
  58.   *env << "\t\".webm\" => a WebM audio(Vorbis)+video(VP8) file\n";  
  59.   *env << "See http://www.live555.com/mediaServer/ for additional documentation.\n";  
  60.   
  61.   // Also, attempt to create a HTTP server for RTSP-over-HTTP tunneling.  
  62.   // Try first with the default HTTP port (80), and then with the alternative HTTP  
  63.   // port numbers (8000 and 8080).  
  64.   
  65.   if (rtspServer->setUpTunnelingOverHTTP(80) || rtspServer->setUpTunnelingOverHTTP(8000) || rtspServer->setUpTunnelingOverHTTP(8080)) {  
  66.     *env << "(We use port " << rtspServer->httpServerPortNum() << " for optional RTSP-over-HTTP tunneling, or for HTTP live streaming (for indexed Transport Stream files only).)\n";  
  67.   } else {  
  68.     *env << "(RTSP-over-HTTP tunneling is not available.)\n";  
  69.   }  
  70.   
  71.   env->taskScheduler().doEventLoop(); // does not return  
  72.   
  73.   return 0; // only to prevent compiler warning  
  74. }  
  75.   
  76. int Rtsp_Server_Start()  
  77. {  
  78.     pthread_create(&id,NULL,server_start,NULL);  
  79. }  
  80.   
  81. int Rtsp_AAC_Frame(unsigned char* frame,int framelen)  
  82. {  
  83.     while(bIsInit == 0)  
  84.     {  
  85.         usleep(1000*100);  
  86.     }  
  87.   
  88.     aac_buf_put(frame,framelen);  
  89.   
  90.     usleep(0);  
  91.     return 0;  
  92. }  
  93.   
  94. int Rtsp_Server_Stop()  
  95. {  
  96.     //printf("destory.....\n");  
  97.     h264_buf_destroy();  
  98.     aac_buf_destroy();  
  99.   
  100. }  
  101.   
  102. int Rtsp_H264_Frame(unsigned char* frame,int framelen)  
  103. {  
  104.     while(b264IsInit == 0)  
  105.     {  
  106.         usleep(1000*100);  
  107.         //printf("usleep(1000*80);\n");  
  108.     }  
  109.       
  110.     int i = 0;  
  111.   
  112. //printf("framelen = %d,count = %d,mod = %d\n",framelen,framelen/H264_BUF_SIZE,framelen%H264_BUF_SIZE);  
  113.     for(i = 0; i < framelen/H264_BUF_SIZE;i++)  
  114.     {  
  115.           
  116.         h264_buf_put(&frame[i*H264_BUF_SIZE],H264_BUF_SIZE);  
  117.           
  118.     }  
  119.   
  120.     int lastsize = framelen % H264_BUF_SIZE;  
  121.     if(lastsize > 0)  
  122.     {  
  123.   
  124.         h264_buf_put(&frame[i*H264_BUF_SIZE],lastsize);  
  125.   
  126.     }  
  127.       
  128.     usleep(0);  
  129.     return 0;  
  130.   
  131. }  
  132.   
  133. int Rtsp_Regist_Start_Routine(CB_FUN fun)  
  134. {  
  135.     startfun = fun;  
  136.     return 0;  
  137. }  
  138.   
  139. int Rtsp_Regist_Stop_Routine(CB_FUN fun)  
  140. {  
  141.     endfun = fun;  
  142.     return 0;  
  143. }  
  144.   
  145. int Rtsp_Port()  
  146. {  
  147.   
  148. }  
  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值