From fe5ae89555ead1863420c1a9c389553e75e4527c Mon Sep 17 00:00:00 2001 From: "N.N." Date: Tue, 30 Mar 2004 02:59:55 +0000 Subject: New in PiDiP 0.12.13 svn path=/trunk/externals/pidip/; revision=1509 --- include/pdp_mp4audiosource.h | 76 ++++++ include/pdp_mp4audiosync.h | 115 +++++++++ include/pdp_mp4config.h | 381 +++++++++++++++++++++++++++++ include/pdp_mp4configset.h | 532 +++++++++++++++++++++++++++++++++++++++++ include/pdp_mp4playermedia.h | 232 ++++++++++++++++++ include/pdp_mp4playersession.h | 249 +++++++++++++++++++ include/pdp_mp4player~.h | 118 +++++++++ include/pdp_mp4rtpbytestream.h | 213 +++++++++++++++++ include/pdp_mp4videosource.h | 90 +++++++ include/pdp_mp4videosync.h | 90 +++++++ 10 files changed, 2096 insertions(+) create mode 100644 include/pdp_mp4audiosource.h create mode 100644 include/pdp_mp4audiosync.h create mode 100644 include/pdp_mp4config.h create mode 100644 include/pdp_mp4configset.h create mode 100644 include/pdp_mp4playermedia.h create mode 100644 include/pdp_mp4playersession.h create mode 100644 include/pdp_mp4player~.h create mode 100644 include/pdp_mp4rtpbytestream.h create mode 100644 include/pdp_mp4videosource.h create mode 100644 include/pdp_mp4videosync.h (limited to 'include') diff --git a/include/pdp_mp4audiosource.h b/include/pdp_mp4audiosource.h new file mode 100644 index 0000000..ec42c3b --- /dev/null +++ b/include/pdp_mp4audiosource.h @@ -0,0 +1,76 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2000, 2001. All Rights Reserved. + * + * Contributor(s): + * Dave Mackie dmackie@cisco.com + * Bill May wmay@cisco.com + * + * Adapted for PD/PDP by Yves Degoyon (ydegoyon@free.fr) + */ + +#ifndef __PDP_MP4AUDIOSOURCE__ +#define __PDP_MP4AUDIOSOURCE__ + +#include +#include +#include + +#include "media_source.h" +#include "audio_encoder.h" + +class CPDPAudioSource : public CMediaSource { + public: + CPDPAudioSource(CLiveConfig *pConfig); + + ~CPDPAudioSource() { + free(m_pcmFrameBuffer); + } + + bool IsDone() { + return false; + } + + float GetProgress() { + return 0.0; + } + + void CPDPAudioSource::DoStart(); + + void CPDPAudioSource::DoStop(); + + void ProcessAudio(u_int8_t* pcmBuffer, u_int32_t pcmBufferSize); + + protected: + int ThreadMain(); + + bool Init(); + + + protected: + int m_maxPasses; + Timestamp m_prevTimestamp; + int m_audioOssMaxBufferSize; + int m_audioOssMaxBufferFrames; + Timestamp *m_timestampOverflowArray; + size_t m_timestampOverflowArrayIndex; + u_int8_t* m_pcmFrameBuffer; + u_int32_t m_pcmFrameSize; + uint32_t m_channelsConfigured; +}; + + +#endif /* __PDP_MP4AUDIOSOURCE__ */ diff --git a/include/pdp_mp4audiosync.h b/include/pdp_mp4audiosync.h new file mode 100644 index 0000000..92098d9 --- /dev/null +++ b/include/pdp_mp4audiosync.h @@ -0,0 +1,115 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2000, 2001. All Rights Reserved. + * + * Contributor(s): + * Bill May wmay@cisco.com + * + * Adapted to PD/PDP by Yves Degoyon (ydegoyon@free.fr) + */ + +/* + * audio.h - provides a class that interfaces between the codec and + * the SDL audio application. Will provide for volume, buffering, + * syncronization + */ + +#ifndef __PDP_MP4AUDIOSYNC__ +#define __PDP_MP4AUDIOSYNC__ + +#include "audio.h" +#include "pdp_mp4player~.h" + +#define DECODE_BUFFERS_MAX 32 + +class CPDPAudioSync : public CAudioSync { + public: + CPDPAudioSync(CPlayerSession *psptr, t_pdp_mp4player *pdp_father); + ~CPDPAudioSync(void); + // APIs from codec + uint8_t *get_audio_buffer(void); + void filled_audio_buffer(uint64_t ts, int resync); + void set_config(int freq, int channels, int format, uint32_t max_buffer_size); + void set_eof(void); + void load_audio_buffer(uint8_t *from, + uint32_t bytes, + uint64_t ts, + int resync); + + // APIs from sync task + int initialize_audio(int have_video); + int is_audio_ready(uint64_t &disptime); + uint64_t check_audio_sync(uint64_t current_time, int &have_eof); + void play_audio(void); + void audio_callback(Uint8 *stream, int len); + void flush_sync_buffers(void); + void flush_decode_buffers(void); + + // Initialization, other APIs + void set_wait_sem(SDL_sem *p) { }; //m_audio_waiting = p; } ; + void set_volume(int volume); + + private: + void audio_convert_data(void *from, uint32_t len); + volatile int m_dont_fill; + uint64_t m_buffer_ts; + uint32_t m_buffer_offset_on; + uint32_t m_buffer_size; + uint32_t m_fill_index, m_play_index; + volatile int m_buffer_filled[DECODE_BUFFERS_MAX]; + uint64_t m_buffer_time[DECODE_BUFFERS_MAX]; + uint64_t m_last_fill_timestamp; + uint64_t m_play_time; + SDL_AudioSpec m_obtained; + uint8_t *m_sample_buffer[DECODE_BUFFERS_MAX]; + int m_config_set; + int m_audio_initialized; + int m_freq; + int m_channels; + int m_format; + int m_resync_required; + int m_audio_paused; + int m_consec_no_buffers; + volatile int m_audio_waiting_buffer; + int m_use_SDL_delay; + uint32_t m_resync_buffer; + SDL_sem *m_audio_waiting; + uint32_t m_skipped_buffers; + uint32_t m_didnt_fill_buffers; + int m_first_time; + int m_first_filled; + uint32_t m_msec_per_frame; + uint64_t m_buffer_latency; + int m_consec_wrong_latency; + int64_t m_wrong_latency_total; + int m_volume; + int m_do_sync; + int m_load_audio_do_next_resync; + uint32_t m_sample_size; + uint32_t m_play_sample_index; + uint32_t m_samples_loaded; + uint32_t m_bytes_per_sample; + uint64_t m_loaded_next_ts; + int m_silence; + void *m_convert_buffer; + t_pdp_mp4player *m_father; +}; + +CPDPAudioSync *pdp_create_audio_sync(CPlayerSession *, t_pdp_mp4player *pdp_father); + +#endif + + diff --git a/include/pdp_mp4config.h b/include/pdp_mp4config.h new file mode 100644 index 0000000..aac8b8b --- /dev/null +++ b/include/pdp_mp4config.h @@ -0,0 +1,381 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2000, 2001. All Rights Reserved. + * + * Contributor(s): + * Dave Mackie dmackie@cisco.com + * Bill May wmay@cisco.com + * + * Adapted for PD/PDP by Yves Degoyon (ydegoyon@free.fr) + */ + +#ifndef __LIVE_CONFIG_H__ +#define __LIVE_CONFIG_H__ + +#include +#include + +#include "pdp_mp4configset.h" + +#include "media_time.h" +#include "video_util_tv.h" + +#define FILE_SOURCE "FILE" +#define URL_SOURCE "URL" + +#define AUDIO_SOURCE_OSS "OSS" +#define AUDIO_SOURCE_PDP "PDP" + +#define AUDIO_ENCODER_FAAC "faac" +#define AUDIO_ENCODER_LAME "lame" +#define AUDIO_ENCODING_NONE "None" +#define AUDIO_ENCODING_PCM16 "PCM16" +#define AUDIO_ENCODING_MP3 "MP3" +#define AUDIO_ENCODING_AAC "AAC" +#define AUDIO_ENCODING_AC3 "AC3" +#define AUDIO_ENCODING_VORBIS "VORBIS" + +#define VIDEO_SOURCE_V4L "V4L" +#define VIDEO_SOURCE_PDP "PDP" + +#define VIDEO_ENCODER_FFMPEG "ffmpeg" +#define VIDEO_ENCODER_DIVX "divx" +#define VIDEO_ENCODER_H26L "h26l" +#define VIDEO_ENCODER_XVID "xvid" +#define VIDEO_ENCODER_H261 "h261" + +#define VIDEO_ENCODING_NONE "None" +#define VIDEO_ENCODING_YUV12 "YUV12" +#define VIDEO_ENCODING_MPEG2 "MPEG2" +#define VIDEO_ENCODING_MPEG4 "MPEG4" +#define VIDEO_ENCODING_H26L "H26L" +#define VIDEO_ENCODING_H261 "H261" + +#define VIDEO_NTSC_FRAME_RATE ((float)29.97) +#define VIDEO_PAL_FRAME_RATE ((float)25.00) + +#define VIDEO_STD_ASPECT_RATIO ((float)1.33) // standard 4:3 +#define VIDEO_LB1_ASPECT_RATIO ((float)2.35) // typical "widescreen" format +#define VIDEO_LB2_ASPECT_RATIO ((float)1.85) // alternate widescreen format +#define VIDEO_LB3_ASPECT_RATIO ((float)1.78) // hdtv 16:9 + +#define MP3_MPEG1_SAMPLES_PER_FRAME 1152 // for MPEG-1 bitrates +#define MP3_MPEG2_SAMPLES_PER_FRAME 576 // for MPEG-2 bitrates + +#define VIDEO_SIGNAL_PAL 0 +#define VIDEO_SIGNAL_NTSC 1 +#define VIDEO_SIGNAL_SECAM 2 + +DECLARE_CONFIG(CONFIG_APP_REAL_TIME); +DECLARE_CONFIG(CONFIG_APP_REAL_TIME_SCHEDULER); +DECLARE_CONFIG(CONFIG_APP_DURATION); +DECLARE_CONFIG(CONFIG_APP_DURATION_UNITS); +DECLARE_CONFIG(CONFIG_APP_FILE_0); +DECLARE_CONFIG(CONFIG_APP_FILE_1); +DECLARE_CONFIG(CONFIG_APP_FILE_2); +DECLARE_CONFIG(CONFIG_APP_FILE_3); +DECLARE_CONFIG(CONFIG_APP_FILE_4); +DECLARE_CONFIG(CONFIG_APP_FILE_5); +DECLARE_CONFIG(CONFIG_APP_FILE_6); +DECLARE_CONFIG(CONFIG_APP_FILE_7); +DECLARE_CONFIG(CONFIG_APP_DEBUG); +DECLARE_CONFIG(CONFIG_APP_LOGLEVEL); +DECLARE_CONFIG(CONFIG_APP_SIGNAL_HALT); + +DECLARE_CONFIG(CONFIG_AUDIO_ENABLE); +DECLARE_CONFIG(CONFIG_AUDIO_SOURCE_TYPE); +DECLARE_CONFIG(CONFIG_AUDIO_SOURCE_NAME); +DECLARE_CONFIG(CONFIG_AUDIO_MIXER_NAME); +DECLARE_CONFIG(CONFIG_AUDIO_INPUT_NAME); +DECLARE_CONFIG(CONFIG_AUDIO_SOURCE_TRACK); +DECLARE_CONFIG(CONFIG_AUDIO_CHANNELS); +DECLARE_CONFIG(CONFIG_AUDIO_SAMPLE_RATE); +DECLARE_CONFIG(CONFIG_AUDIO_BIT_RATE_KBPS); +DECLARE_CONFIG(CONFIG_AUDIO_BIT_RATE); +DECLARE_CONFIG(CONFIG_AUDIO_ENCODING); +DECLARE_CONFIG(CONFIG_AUDIO_ENCODER); +DECLARE_CONFIG(CONFIG_AUDIO_OSS_USE_SMALL_FRAGS); +DECLARE_CONFIG(CONFIG_AUDIO_OSS_FRAGMENTS); +DECLARE_CONFIG(CONFIG_AUDIO_OSS_FRAG_SIZE); + +DECLARE_CONFIG(CONFIG_VIDEO_ENABLE); +DECLARE_CONFIG(CONFIG_VIDEO_SOURCE_TYPE); +DECLARE_CONFIG(CONFIG_VIDEO_SOURCE_NAME); +DECLARE_CONFIG(CONFIG_VIDEO_INPUT); +DECLARE_CONFIG(CONFIG_VIDEO_SIGNAL); +DECLARE_CONFIG(CONFIG_VIDEO_TUNER); +DECLARE_CONFIG(CONFIG_VIDEO_CHANNEL_LIST_INDEX); +DECLARE_CONFIG(CONFIG_VIDEO_CHANNEL_INDEX); +DECLARE_CONFIG(CONFIG_VIDEO_SOURCE_TRACK); +DECLARE_CONFIG(CONFIG_VIDEO_PREVIEW); +DECLARE_CONFIG(CONFIG_VIDEO_RAW_PREVIEW); +DECLARE_CONFIG(CONFIG_VIDEO_ENCODED_PREVIEW); +DECLARE_CONFIG(CONFIG_VIDEO_ENCODER); +DECLARE_CONFIG(CONFIG_VIDEO_ENCODING); +DECLARE_CONFIG(CONFIG_VIDEO_RAW_WIDTH); +DECLARE_CONFIG(CONFIG_VIDEO_RAW_HEIGHT); +DECLARE_CONFIG(CONFIG_VIDEO_ASPECT_RATIO); +DECLARE_CONFIG(CONFIG_VIDEO_FRAME_RATE); +DECLARE_CONFIG(CONFIG_VIDEO_KEY_FRAME_INTERVAL); +DECLARE_CONFIG(CONFIG_VIDEO_BIT_RATE); +DECLARE_CONFIG(CONFIG_VIDEO_PROFILE_ID); +DECLARE_CONFIG(CONFIG_VIDEO_BRIGHTNESS); +DECLARE_CONFIG(CONFIG_VIDEO_HUE); +DECLARE_CONFIG(CONFIG_VIDEO_COLOR); +DECLARE_CONFIG(CONFIG_VIDEO_CONTRAST); +DECLARE_CONFIG(CONFIG_VIDEO_TIMEBITS); +DECLARE_CONFIG(CONFIG_V4L_CACHE_TIMESTAMP); +DECLARE_CONFIG(CONFIG_VIDEO_H261_QUALITY); +DECLARE_CONFIG(CONFIG_VIDEO_H261_QUALITY_ADJ_FRAMES); +DECLARE_CONFIG(CONFIG_VIDEO_CAP_BUFF_COUNT); + + +DECLARE_CONFIG(CONFIG_RECORD_ENABLE); +DECLARE_CONFIG(CONFIG_RECORD_RAW_AUDIO); +DECLARE_CONFIG(CONFIG_RECORD_RAW_VIDEO); +DECLARE_CONFIG(CONFIG_RECORD_ENCODED_AUDIO); +DECLARE_CONFIG(CONFIG_RECORD_ENCODED_VIDEO); +DECLARE_CONFIG(CONFIG_RECORD_MP4_FILE_NAME); +DECLARE_CONFIG(CONFIG_RECORD_MP4_HINT_TRACKS); +DECLARE_CONFIG(CONFIG_RECORD_MP4_OVERWRITE); +DECLARE_CONFIG(CONFIG_RECORD_MP4_OPTIMIZE); + +DECLARE_CONFIG(CONFIG_RTP_ENABLE); +DECLARE_CONFIG(CONFIG_RTP_DEST_ADDRESS); // for video +DECLARE_CONFIG(CONFIG_RTP_AUDIO_DEST_PORT); +DECLARE_CONFIG(CONFIG_RTP_VIDEO_DEST_PORT); +DECLARE_CONFIG(CONFIG_RTP_RECV_BUFFER_TIME); +DECLARE_CONFIG(CONFIG_RTP_PAYLOAD_SIZE); +DECLARE_CONFIG(CONFIG_RTP_MCAST_TTL); +DECLARE_CONFIG(CONFIG_RTP_DISABLE_TS_OFFSET); +DECLARE_CONFIG(CONFIG_RTP_USE_SSM); +DECLARE_CONFIG(CONFIG_SDP_FILE_NAME); +DECLARE_CONFIG(CONFIG_RTP_AUDIO_DEST_ADDRESS); +DECLARE_CONFIG(CONFIG_RTP_USE_MP3_PAYLOAD_14); +DECLARE_CONFIG(CONFIG_RTP_NO_B_RR_0); +DECLARE_CONFIG(CONFIG_RAW_ENABLE); +DECLARE_CONFIG(CONFIG_RAW_PCM_FILE_NAME); +DECLARE_CONFIG(CONFIG_RAW_PCM_FIFO); +DECLARE_CONFIG(CONFIG_RAW_YUV_FILE_NAME); +DECLARE_CONFIG(CONFIG_RAW_YUV_FIFO); + + +#ifdef DECLARE_CONFIG_VARIABLES +static SConfigVariable PdpConfigVariables[] = { + + CONFIG_BOOL(CONFIG_APP_REAL_TIME, "isRealTime", true), + CONFIG_BOOL(CONFIG_APP_REAL_TIME_SCHEDULER, "useRealTimeScheduler", true), + CONFIG_INT(CONFIG_APP_DURATION, "duration", 1), + CONFIG_INT(CONFIG_APP_DURATION_UNITS, "durationUnits", 60), + + CONFIG_STRING(CONFIG_APP_FILE_0, "file0", ""), + CONFIG_STRING(CONFIG_APP_FILE_1, "file1", ""), + CONFIG_STRING(CONFIG_APP_FILE_2, "file2", ""), + CONFIG_STRING(CONFIG_APP_FILE_3, "file3", ""), + CONFIG_STRING(CONFIG_APP_FILE_4, "file4", ""), + CONFIG_STRING(CONFIG_APP_FILE_5, "file5", ""), + CONFIG_STRING(CONFIG_APP_FILE_6, "file6", ""), + CONFIG_STRING(CONFIG_APP_FILE_7, "file7", ""), + + CONFIG_BOOL(CONFIG_APP_DEBUG, "debug", false), + CONFIG_INT(CONFIG_APP_LOGLEVEL, "logLevel", 0), + CONFIG_STRING(CONFIG_APP_SIGNAL_HALT, "signalHalt", "sighup"), + + // AUDIO + + CONFIG_BOOL(CONFIG_AUDIO_ENABLE, "audioEnable", true), + CONFIG_STRING(CONFIG_AUDIO_SOURCE_TYPE, "audioSourceType", AUDIO_SOURCE_PDP), + CONFIG_STRING(CONFIG_AUDIO_SOURCE_NAME, "audioDevice", "/dev/dsp"), + CONFIG_STRING(CONFIG_AUDIO_MIXER_NAME, "audioMixer", "/dev/mixer"), + CONFIG_STRING(CONFIG_AUDIO_INPUT_NAME, "audioInput", "mix"), + + CONFIG_INT(CONFIG_AUDIO_SOURCE_TRACK, "audioSourceTrack", 0), + CONFIG_INT(CONFIG_AUDIO_CHANNELS, "audioChannels", 2), + CONFIG_INT(CONFIG_AUDIO_SAMPLE_RATE, "audioSampleRate", 44100), + CONFIG_INT(CONFIG_AUDIO_BIT_RATE_KBPS, "audioBitRate", 128), + CONFIG_INT(CONFIG_AUDIO_BIT_RATE, "audioBitRateBps", 128000), + CONFIG_STRING(CONFIG_AUDIO_ENCODING, "audioEncoding", AUDIO_ENCODING_AAC), + CONFIG_STRING(CONFIG_AUDIO_ENCODER, "audioEncoder", AUDIO_ENCODER_FAAC), + + CONFIG_BOOL(CONFIG_AUDIO_OSS_USE_SMALL_FRAGS, "audioOssUseSmallFrags", true), + CONFIG_INT(CONFIG_AUDIO_OSS_FRAGMENTS, "audioOssFragments", 128), + CONFIG_INT(CONFIG_AUDIO_OSS_FRAG_SIZE, "audioOssFragSize", 8), + + // VIDEO + + CONFIG_BOOL(CONFIG_VIDEO_ENABLE, "videoEnable", true), + CONFIG_STRING(CONFIG_VIDEO_SOURCE_TYPE, "videoSourceType", VIDEO_SOURCE_PDP), + CONFIG_STRING(CONFIG_VIDEO_SOURCE_NAME, "videoDevice", "/dev/video0"), + CONFIG_INT(CONFIG_VIDEO_INPUT, "videoInput", 1), + CONFIG_INT(CONFIG_VIDEO_SIGNAL, "videoSignal", VIDEO_SIGNAL_NTSC), + + CONFIG_INT(CONFIG_VIDEO_TUNER, "videoTuner", -1), + CONFIG_INT(CONFIG_VIDEO_CHANNEL_LIST_INDEX, "videoChannelListIndex", 0), + CONFIG_INT(CONFIG_VIDEO_CHANNEL_INDEX, "videoChannelIndex", 1), + + CONFIG_INT(CONFIG_VIDEO_SOURCE_TRACK, "videoSourceTrack", 0), + + CONFIG_BOOL(CONFIG_VIDEO_PREVIEW, "videoPreview", true), + CONFIG_BOOL(CONFIG_VIDEO_RAW_PREVIEW, "videoRawPreview", false), + CONFIG_BOOL(CONFIG_VIDEO_ENCODED_PREVIEW, "videoEncodedPreview", true), + + CONFIG_STRING(CONFIG_VIDEO_ENCODER, "videoEncoder", VIDEO_ENCODER_XVID), + CONFIG_STRING(CONFIG_VIDEO_ENCODING, "videoEncoding", VIDEO_ENCODING_MPEG4), + + CONFIG_INT(CONFIG_VIDEO_RAW_WIDTH, "videoRawWidth", 320), + CONFIG_INT(CONFIG_VIDEO_RAW_HEIGHT, "videoRawHeight", 240), + CONFIG_FLOAT(CONFIG_VIDEO_ASPECT_RATIO, "videoAspectRatio", VIDEO_STD_ASPECT_RATIO), + CONFIG_FLOAT(CONFIG_VIDEO_FRAME_RATE, "videoFrameRate", VIDEO_PAL_FRAME_RATE), + CONFIG_FLOAT(CONFIG_VIDEO_KEY_FRAME_INTERVAL, "videoKeyFrameInterval", 2.0), + + CONFIG_INT(CONFIG_VIDEO_BIT_RATE, "videoBitRate", 128), + CONFIG_INT(CONFIG_VIDEO_PROFILE_ID, "videoProfileId", MPEG4_SP_L3), + + CONFIG_INT(CONFIG_VIDEO_BRIGHTNESS, "videoBrightness", 50), + CONFIG_INT(CONFIG_VIDEO_HUE, "videoHue", 50), + CONFIG_INT(CONFIG_VIDEO_COLOR, "videoColor", 50), + CONFIG_INT(CONFIG_VIDEO_CONTRAST, "videoContrast", 50), + + CONFIG_INT(CONFIG_VIDEO_TIMEBITS, "videoTimebits", 0), + + CONFIG_BOOL(CONFIG_V4L_CACHE_TIMESTAMP, "videoTimestampCache", true), + CONFIG_INT(CONFIG_VIDEO_H261_QUALITY, "videoH261Quality", 10), + CONFIG_INT(CONFIG_VIDEO_H261_QUALITY_ADJ_FRAMES, "videoH261QualityAdjFrames", 8), + + CONFIG_INT(CONFIG_VIDEO_CAP_BUFF_COUNT, "videoCaptureBuffersCount", 16), + + // RECORD + CONFIG_BOOL(CONFIG_RECORD_ENABLE, "recordEnable", true), + CONFIG_BOOL(CONFIG_RECORD_RAW_AUDIO, "recordRawAudio", false), + CONFIG_BOOL(CONFIG_RECORD_RAW_VIDEO, "recordRawVideo", false), + CONFIG_BOOL(CONFIG_RECORD_ENCODED_AUDIO, "recordEncodedAudio", true), + CONFIG_BOOL(CONFIG_RECORD_ENCODED_VIDEO, "recordEncodedVideo", true), + + CONFIG_STRING(CONFIG_RECORD_MP4_FILE_NAME, "recordMp4File", "capture.mp4"), + CONFIG_BOOL(CONFIG_RECORD_MP4_HINT_TRACKS, "recordMp4HintTracks", true), + CONFIG_BOOL(CONFIG_RECORD_MP4_OVERWRITE, "recordMp4Overwrite", true), + CONFIG_BOOL(CONFIG_RECORD_MP4_OPTIMIZE, "recordMp4Optimize", false), + + // RTP + + CONFIG_BOOL(CONFIG_RTP_ENABLE, "rtpEnable", true), + CONFIG_STRING(CONFIG_RTP_DEST_ADDRESS, "rtpDestAddress", "127.0.0.1"), + CONFIG_STRING(CONFIG_RTP_AUDIO_DEST_ADDRESS, "audioRtpDestAddress", "127.0.0.1"), + + CONFIG_INT(CONFIG_RTP_AUDIO_DEST_PORT, "rtpAudioDestPort", 8000), + CONFIG_INT(CONFIG_RTP_VIDEO_DEST_PORT, "rtpVideoDestPort", 7070), + + CONFIG_INT(CONFIG_RTP_PAYLOAD_SIZE, "rtpPayloadSize", 1460), + CONFIG_INT(CONFIG_RTP_MCAST_TTL, "rtpMulticastTtl", 15), + + CONFIG_BOOL(CONFIG_RTP_DISABLE_TS_OFFSET, "rtpDisableTimestampOffset", false), + CONFIG_BOOL(CONFIG_RTP_USE_SSM, "rtpUseSingleSourceMulticast", false), + + CONFIG_STRING(CONFIG_SDP_FILE_NAME, "sdpFile", "capture.sdp"), + + CONFIG_BOOL(CONFIG_RTP_USE_MP3_PAYLOAD_14, "rtpUseMp4RtpPayload14", false), + CONFIG_BOOL(CONFIG_RTP_NO_B_RR_0, "rtpNoBRR0", false), + + // RAW sink + + CONFIG_BOOL(CONFIG_RAW_ENABLE, "rawEnable", false), + CONFIG_STRING(CONFIG_RAW_PCM_FILE_NAME, "rawAudioFile", "capture.pcm"), + CONFIG_BOOL(CONFIG_RAW_PCM_FIFO, "rawAudioUseFifo", false), + + CONFIG_STRING(CONFIG_RAW_YUV_FILE_NAME, "rawVideoFile", "capture.yuv"), + CONFIG_BOOL(CONFIG_RAW_YUV_FIFO, "rawVideoUseFifo", false) + +}; +#endif + +// forward declarations +class CVideoCapabilities; +class CAudioCapabilities; +class CLiveConfig; + +// some configuration utility routines +void GenerateMpeg4VideoConfig(CLiveConfig* pConfig); +bool GenerateSdpFile(CLiveConfig* pConfig); +struct session_desc_t; + +session_desc_t *createSdpDescription(CLiveConfig *pConfig, + char *sAudioDestAddr, + char *sVideoDestAddr, + int ttl, + bool allow_rtcp, + int video_port, + int audio_port); + +class CLiveConfig : public CConfigSet { +public: + CLiveConfig(SConfigVariable* variables, + config_index_t numVariables, const char* defaultFileName); + + ~CLiveConfig(); + + // recalculate derived values + void Update(); + void UpdateFileHistory(const char* fileName); + void UpdateVideo(); + void CalculateVideoFrameSize(); + void UpdateAudio(); + void UpdateRecord(); + + bool IsOneSource(); + bool IsCaptureVideoSource(); + bool IsCaptureAudioSource(); + bool IsFileVideoSource(); + bool IsFileAudioSource(); + + bool SourceRawVideo() { + return false; + } + + bool SourceRawAudio() { + return false; + } + +public: + // command line configuration + bool m_appAutomatic; + + // derived, shared video configuration + CVideoCapabilities* m_videoCapabilities; + bool m_videoEncode; + u_int32_t m_videoPreviewWindowId; + u_int16_t m_videoWidth; + u_int16_t m_videoHeight; + u_int16_t m_videoMaxWidth; + u_int16_t m_videoMaxHeight; + u_int32_t m_ySize; + u_int32_t m_uvSize; + u_int32_t m_yuvSize; + bool m_videoNeedRgbToYuv; + u_int16_t m_videoMpeg4ConfigLength; + u_int8_t* m_videoMpeg4Config; + u_int32_t m_videoMaxVopSize; + u_int8_t m_videoTimeIncrBits; + + // derived, shared audio configuration + CAudioCapabilities* m_audioCapabilities; + bool m_audioEncode; + + // derived, shared file configuration + u_int64_t m_recordEstFileSize; +}; + +#endif /* __LIVE_CONFIG_H__ */ + diff --git a/include/pdp_mp4configset.h b/include/pdp_mp4configset.h new file mode 100644 index 0000000..a20d260 --- /dev/null +++ b/include/pdp_mp4configset.h @@ -0,0 +1,532 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2000, 2001. All Rights Reserved. + * + * Contributor(s): + * Dave Mackie dmackie@cisco.com + * Bill May wmay@cisco.com + * + * Adapted for PD/PDP by Yves Degoyon (ydegoyon@free.fr) + */ + +#ifndef __CONFIG_SET_H__ +#define __CONFIG_SET_H__ + +#include + +#ifndef CONFIG_SAFETY +#define CONFIG_SAFETY 1 +#endif + +typedef u_int32_t config_integer_t; + +typedef u_int16_t config_index_t; + + +enum ConfigException { + CONFIG_ERR_INAME, + CONFIG_ERR_TYPE, + CONFIG_ERR_MEMORY, +}; + +// TBD type specific exception info and printing utility +class CConfigException { +public: + CConfigException(ConfigException e) { + type = e; + fprintf( stderr, "pdp_mp4configset : exception : type : %d\n", e ); + } + ConfigException type; +}; + +#define CONFIG_MAX_STRLEN 255 + +// TBD weld this in, and throw exception +inline char* stralloc(const char* src) { + char* dst = (char*)malloc(strlen(src)+1); + if (dst) { + strcpy(dst, src); + } + return dst; +} + +enum ConfigType { + CONFIG_TYPE_UNDEFINED, + CONFIG_TYPE_INTEGER, + CONFIG_TYPE_BOOL, + CONFIG_TYPE_STRING, + CONFIG_TYPE_FLOAT +}; + +union UConfigValue { + UConfigValue(void) { + m_svalue = NULL; + } + UConfigValue(config_integer_t ivalue) { + m_ivalue = ivalue; + } + UConfigValue(bool bvalue) { + m_bvalue = bvalue; + } + UConfigValue(char* svalue) { + m_svalue = svalue; + } + UConfigValue(float fvalue) { + m_fvalue = fvalue; + } + + config_integer_t m_ivalue; + bool m_bvalue; + char* m_svalue; + float m_fvalue; +}; + +struct SConfigVariable { + config_index_t *m_iName; + const char* m_sName; + ConfigType m_type; + UConfigValue m_defaultValue; + UConfigValue m_value; + + const char* ToAscii() { + static char sBuf[CONFIG_MAX_STRLEN+3]; + switch (m_type) { + case CONFIG_TYPE_INTEGER: + sprintf(sBuf, "%d", m_value.m_ivalue); + return sBuf; + case CONFIG_TYPE_BOOL: + sprintf(sBuf, "%d", m_value.m_bvalue); + return sBuf; + case CONFIG_TYPE_STRING: + if (strchr(m_value.m_svalue, ' ')) { + sBuf[0] = '"'; + strncpy(&sBuf[1], m_value.m_svalue, CONFIG_MAX_STRLEN); + strcpy(&sBuf[ + MIN(strlen(m_value.m_svalue), CONFIG_MAX_STRLEN)+1], "\""); + } + return m_value.m_svalue; + case CONFIG_TYPE_FLOAT: + sprintf(sBuf, "%f", m_value.m_fvalue); + return sBuf; + default: + return ""; + } + } + + bool FromAscii(const char* s) { + switch (m_type) { + case CONFIG_TYPE_INTEGER: + return (sscanf(s, " %i ", &m_value.m_ivalue) == 1); + case CONFIG_TYPE_BOOL: + // OPTION could add "yes/no", "true/false" + if (sscanf(s, " %u ", &m_value.m_ivalue) != 1) { + return false; + } + m_value.m_bvalue = m_value.m_ivalue ? true : false; + return true; + case CONFIG_TYPE_STRING: + // N.B. assuming m_svalue has been alloc'ed + { + size_t len = strlen(s); + free(m_value.m_svalue); + if (*s == '"' && s[len] == '"') { + m_value.m_svalue = strdup(s + 1); + m_value.m_svalue[len - 1] = '\0'; + } else { + m_value.m_svalue = strdup(s); + } + if (m_value.m_svalue == NULL) { + throw new CConfigException(CONFIG_ERR_MEMORY); + } + return true; + } + case CONFIG_TYPE_FLOAT: + return (sscanf(s, " %f ", &m_value.m_fvalue) == 1); + default: + return false; + } + } + + void SetToDefault(void) { + switch (m_type) { + case CONFIG_TYPE_INTEGER: + m_value.m_ivalue = m_defaultValue.m_ivalue; + break; + case CONFIG_TYPE_BOOL: + m_value.m_bvalue = m_defaultValue.m_bvalue; + break; + case CONFIG_TYPE_STRING: + // free(m_value.m_svalue); + m_value.m_svalue = stralloc(m_defaultValue.m_svalue); + if (m_value.m_svalue == NULL) { + throw new CConfigException(CONFIG_ERR_MEMORY); + } + break; + case CONFIG_TYPE_FLOAT: + m_value.m_fvalue = m_defaultValue.m_fvalue; + break; + default: + break; + } + } + + bool IsValueDefault(void) { + switch (m_type) { + case CONFIG_TYPE_INTEGER: + return m_value.m_ivalue == m_defaultValue.m_ivalue; + case CONFIG_TYPE_BOOL: + return m_value.m_bvalue == m_defaultValue.m_bvalue; + case CONFIG_TYPE_STRING: + return (strcmp(m_value.m_svalue, m_defaultValue.m_svalue) == 0); + case CONFIG_TYPE_FLOAT: + return m_value.m_fvalue == m_defaultValue.m_fvalue; + default: + return false; + } + } + void CleanUpConfig(void) { + if (m_type == CONFIG_TYPE_STRING) { + CHECK_AND_FREE(m_value.m_svalue); + } + } +}; + +struct SUnknownConfigVariable { + struct SUnknownConfigVariable *next; + char *value; +}; + +class CConfigSet { +public: + CConfigSet(SConfigVariable* variables, + config_index_t numVariables, + const char* defaultFileName) { + uint32_t size; + m_fileName = NULL; + m_debug = false; + m_variables = variables; + m_numVariables = numVariables; + size = sizeof(SConfigVariable) * numVariables; + m_variables = + (SConfigVariable*)malloc(size); + + memcpy(m_variables, variables, size); + m_defaultFileName = strdup(defaultFileName); + SetToDefaults(); + m_unknown_head = NULL; + }; + + ~CConfigSet() { + free(m_fileName); + for (config_index_t i = 0; i < m_numVariables; i++) { + m_variables[i].CleanUpConfig(); + } + free(m_variables); + m_variables = NULL; + SUnknownConfigVariable *ptr = m_unknown_head; + while (ptr != NULL) { + m_unknown_head = ptr->next; + free(ptr->value); + free(ptr); + ptr = m_unknown_head; + } + CHECK_AND_FREE(m_defaultFileName); + } + + void InitializeIndexes(void) { + for (config_index_t ix = 0; ix < m_numVariables; ix++) { + *m_variables[ix].m_iName = ix; + } + } + + void AddConfigVariables (SConfigVariable* vars, + config_index_t numVariables) { + config_index_t start = m_numVariables; + uint32_t size = sizeof(SConfigVariable) * + (m_numVariables + numVariables); + m_variables = (SConfigVariable*)realloc(m_variables, size); + memcpy(&m_variables[m_numVariables], vars, + numVariables * sizeof(SConfigVariable)); + m_numVariables += numVariables; + SetToDefaults(start); + } + + const char* GetFileName() { + return m_fileName; + } + + inline void CheckIName(config_index_t iName) { + if (iName >= m_numVariables) { + throw new CConfigException(CONFIG_ERR_INAME); + } + if (*m_variables[iName].m_iName != iName) { + throw new CConfigException(CONFIG_ERR_INAME); + } + } + + inline void CheckIntegerType(config_index_t iName) { + if (m_variables[iName].m_type != CONFIG_TYPE_INTEGER) { + throw new CConfigException(CONFIG_ERR_TYPE); + } + } + + inline void CheckBoolType(config_index_t iName) { + if (m_variables[iName].m_type != CONFIG_TYPE_BOOL) { + throw new CConfigException(CONFIG_ERR_TYPE); + } + } + + inline void CheckStringType(config_index_t iName) { + if (m_variables[iName].m_type != CONFIG_TYPE_STRING) { + throw new CConfigException(CONFIG_ERR_TYPE); + } + } + + inline void CheckFloatType(config_index_t iName) { + if (m_variables[iName].m_type != CONFIG_TYPE_FLOAT) { + throw new CConfigException(CONFIG_ERR_TYPE); + } + } + + inline bool IsDefault (const config_index_t iName) { +#if CONFIG_SAFETY + CheckIName(iName); + CheckIntegerType(iName); +#endif + return m_variables[iName].IsValueDefault(); + }; + + inline config_integer_t GetIntegerValue(const config_index_t iName) { +#if CONFIG_SAFETY + CheckIName(iName); + CheckIntegerType(iName); +#endif + return m_variables[iName].m_value.m_ivalue; + } + + inline void SetIntegerValue(const config_index_t iName, + config_integer_t ivalue) { +#if CONFIG_SAFETY + CheckIName(iName); + CheckIntegerType(iName); +#endif + m_variables[iName].m_value.m_ivalue = ivalue; + } + + inline bool GetBoolValue(const config_index_t iName) { +#if CONFIG_SAFETY + CheckIName(iName); + CheckBoolType(iName); +#endif + return m_variables[iName].m_value.m_bvalue;; + } + + inline void SetBoolValue(const config_index_t iName, bool bvalue) { +#if CONFIG_SAFETY + CheckIName(iName); + CheckBoolType(iName); +#endif + m_variables[iName].m_value.m_bvalue = bvalue; + } + + inline char* GetStringValue(const config_index_t iName) { +#if CONFIG_SAFETY + CheckIName(iName); + CheckStringType(iName); +#endif + return m_variables[iName].m_value.m_svalue; + } + + inline void SetStringValue(const config_index_t iName, const char* svalue) { + printf ( "setting variable : %d to : %s\n", iName, svalue ); +#if CONFIG_SAFETY + CheckIName(iName); + CheckStringType(iName); +#endif + if (svalue == m_variables[iName].m_value.m_svalue) { + return; + } + // free(m_variables[iName].m_value.m_svalue); + m_variables[iName].m_value.m_svalue = stralloc(svalue); + if (m_variables[iName].m_value.m_svalue == NULL) { + throw new CConfigException(CONFIG_ERR_MEMORY); + } + } + + inline float GetFloatValue(const config_index_t iName) { +#if CONFIG_SAFETY + CheckIName(iName); + CheckFloatType(iName); +#endif + return m_variables[iName].m_value.m_fvalue; + } + + inline void SetFloatValue(const config_index_t iName, float fvalue) { +#if CONFIG_SAFETY + CheckIName(iName); + CheckFloatType(iName); +#endif + m_variables[iName].m_value.m_fvalue = fvalue; + } + + void SetToDefaults(int start = 0) { + for (config_index_t i = start; i < m_numVariables; i++) { + m_variables[i].SetToDefault(); + } + } + + void SetToDefault(const config_index_t iName) { + m_variables[iName].SetToDefault(); + } + + void ProcessLine (char *line) { + // comment + if (line[0] == '#') { + return; + } + char* s = line; + while (*s != '\0') s++; + s--; + while (isspace(*s)) { + *s = '\0'; + s--; + } + s = line; + + SConfigVariable* var = FindByName(strsep(&s, "=")); + if (var == NULL || s == NULL) { + if (s != NULL) { + *(s - 1) = '='; // restore seperation character + SUnknownConfigVariable *ptr; + ptr = MALLOC_STRUCTURE(SUnknownConfigVariable); + ptr->next = m_unknown_head; + ptr->value = strdup(line); + m_unknown_head = ptr; + } + if (m_debug) { + fprintf(stderr, "bad config line %s\n", s); + } + return; + } + if (!var->FromAscii(s)) { + if (m_debug) { + fprintf(stderr, "bad config value in line %s\n", s); + } + } + } + + bool ReadFromFile(const char* fileName) { + free(m_fileName); + m_fileName = stralloc(fileName); + FILE* pFile = fopen(fileName, "r"); + if (pFile == NULL) { + if (m_debug) { + fprintf(stderr, "couldn't open file %s\n", fileName); + } + return false; + } + char line[256]; + while (fgets(line, sizeof(line), pFile)) { + ProcessLine(line); + } + fclose(pFile); + return true; + } + + bool WriteToFile(const char* fileName, bool allValues = false) { + FILE* pFile = fopen(fileName, "w"); + config_index_t i; + SConfigVariable *var; + SUnknownConfigVariable *ptr; + + if (pFile == NULL) { + if (m_debug) { + fprintf(stderr, "couldn't open file %s\n", fileName); + } + return false; + } + for (i = 0; i < m_numVariables; i++) { + var = &m_variables[i]; + if (allValues || !var->IsValueDefault()) { + fprintf(pFile, "%s=%s\n", var->m_sName, var->ToAscii()); + } + } + ptr = m_unknown_head; + while (ptr != NULL) { + fprintf(pFile, "%s\n", ptr->value); + ptr = ptr->next; + } + fclose(pFile); + return true; + } + + bool ReadDefaultFile(void) { + return ReadFromFile(m_defaultFileName); + } + bool WriteDefaultFile(void) { + return WriteToFile(m_defaultFileName); + } + + void SetDebug(bool debug = true) { + m_debug = debug; + } + +protected: + SConfigVariable* FindByName(const char* sName) { + for (config_index_t i = 0; i < m_numVariables; i++) { + if (!strcasecmp(sName, m_variables[i].m_sName)) { + return &m_variables[i]; + } + } + return NULL; + }; + +protected: + SConfigVariable* m_variables; + config_index_t m_numVariables; + const char* m_defaultFileName; + bool m_debug; + char* m_fileName; + SUnknownConfigVariable *m_unknown_head; +}; + +// To define configuration variables - first DECLARE_CONFIG in a +// .h file. Then in either a C++ or h file, define a static array +// of configuration variables using CONFIG_BOOL, CONFIG_FLOAT, CONFIG_INT +// or CONFIG_STRING. You can include the .h anywhere you use the variable - +// in a .cpp, you must include the .h file with DECLARE_CONFIG_VARIABLES +// defined before the .h file. Note - if you're already including mp4live.h, +// you need to #define the DECLARE_CONFIG_VARIABLES after the include. +// +// Note - you want to add the config variables BEFORE the ReadFromFile +// call +#ifdef DECLARE_CONFIG_VARIABLES +#define DECLARE_CONFIG(a) config_index_t (a); +#else +#define DECLARE_CONFIG(a) extern config_index_t (a); +#endif + +#define CONFIG_BOOL(var, name, defval) \ + { &(var), (name), CONFIG_TYPE_BOOL, (defval), } +#define CONFIG_FLOAT(var, name, defval) \ + { &(var), (name), CONFIG_TYPE_FLOAT,(float) (defval), } +#define CONFIG_INT(var, name, defval) \ + { &(var), (name), CONFIG_TYPE_INTEGER,(config_integer_t) (defval), } +#define CONFIG_STRING(var, name, defval) \ + { &(var), (name), CONFIG_TYPE_STRING, (defval), } + + +#endif /* __CONFIG_SET_H__ */ diff --git a/include/pdp_mp4playermedia.h b/include/pdp_mp4playermedia.h new file mode 100644 index 0000000..025fb57 --- /dev/null +++ b/include/pdp_mp4playermedia.h @@ -0,0 +1,232 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2000, 2001. All Rights Reserved. + * + * Contributor(s): + * Bill May wmay@cisco.com + * + * Adapted to PD/PDP by Yves Degoyon (ydegoyon@free.fr) + */ + +/* + * player_media.h - provides CPlayerMedia class, which defines the + * interface to a particular media steam. + */ + +#ifndef __PLAYER_MEDIA_H__ +#define __PLAYER_MEDIA_H__ + +#include +#include +#include +#include +#include +#include "our_bytestream.h" +#include "our_msg_queue.h" +#include "codec_plugin.h" + +class CPlayerSession; +class CPDPAudioSync; +class CPDPVideoSync; +class C2ConsecIpPort; +class COurInByteStream; +class CRtpByteStreamBase; + +class CPlayerMedia { + public: + CPlayerMedia(CPlayerSession *p); + ~CPlayerMedia(); + /* API routine - create - for RTP stream */ + int create_streaming(media_desc_t *sdp_media, + char *errmsg, + uint32_t errlen, + int on_demand, + int use_rtsp, + int media_number_in_session); + /* API routine - create - where we provide the bytestream */ + int create(COurInByteStream *b, + int is_video, + char *errmsg = NULL, + uint32_t errlen = 0, + int streaming = 0); + /* API routine - play, pause */ + int do_play(double start_time_offset, char *errmsg, uint32_t errlen); + int do_pause(void); + int is_video(void) { return (m_is_video); }; + double get_max_playtime(void); + /* API routine - interface for decoding start/continue */ + void start_decoding(void); + void bytestream_primed(void); + /* API routine - ip port information */ + uint16_t get_our_port (void) { return m_our_port; }; + void set_server_port (uint16_t port) { m_server_port = port; }; + uint16_t get_server_port (void) { return m_server_port; }; + + media_desc_t *get_sdp_media_desc (void) { return m_media_info; }; + void set_source_addr (char *s) + { + if (m_source_addr != NULL) free(m_source_addr); + m_source_addr = s; + } + const char *get_source_addr(void); + CPlayerMedia *get_next (void) { return m_next; }; + void set_next (CPlayerMedia *newone) { m_next = newone; }; + int decode_thread(void); + + /* Public RTP routines - receive thread, callback, and routines to + * pass information from rtsp to rtp byte stream + */ + int recv_thread(void); + void recv_callback(struct rtp *session, rtp_event *e); + void set_rtp_ssrc (uint32_t ssrc) + { m_rtp_ssrc = ssrc; m_rtp_ssrc_set = TRUE;}; + void set_rtp_base_ts(uint32_t time); + void set_rtp_base_seq(uint16_t seq); + + void set_video_sync(CPDPVideoSync *p) {m_video_sync = p;}; + void set_audio_sync(CPDPAudioSync *p) {m_audio_sync = p;}; + + const video_info_t *get_video_info (void) { return m_video_info; }; + const audio_info_t *get_audio_info (void) { return m_audio_info; }; + + int create_video_plugin(const codec_plugin_t *p, + const char *compressor, + int profile, + int type, + format_list_t *sdp_media, + video_info_t *video, + const uint8_t *user_data, + uint32_t userdata_size); + int create_audio_plugin(const codec_plugin_t *p, + const char *compressor, + int profile, + int type, + format_list_t *sdp_media, + audio_info_t *audio, + const uint8_t *user_data, + uint32_t userdata_size); + void set_plugin_data (const codec_plugin_t *p, + codec_data_t *d, + video_vft_t *v, + audio_vft_t *a); + int get_plugin_status(char *buffer, uint32_t buflen); + void set_user_data (const uint8_t *udata, int length) { + m_user_data = udata; + m_user_data_size = length; + } + rtsp_session_t *get_rtsp_session(void) { return m_rtsp_session; }; + void rtp_init_tcp(void); + void rtp_periodic(void); + void rtp_start(void); + void rtp_end(void); + int rtp_receive_packet(unsigned char interleaved, struct rtp_packet *, int len); + int rtcp_send_packet(uint8_t *buffer, int buflen); + int get_rtp_media_number (void) { return m_rtp_media_number_in_session; }; + void syncronize_rtp_bytestreams(rtcp_sync_t *sync); + private: + int create_common(int is_video, char *errmsg, uint32_t errlen); + void wait_on_bytestream(void); + int m_streaming; + int m_is_video; + int m_paused; + CPlayerMedia *m_next; + CPlayerSession *m_parent; + media_desc_t *m_media_info; + format_list_t *m_media_fmt; // format currently running. + rtsp_session_t *m_rtsp_session; + C2ConsecIpPort *m_ports; + in_port_t m_our_port; + in_port_t m_server_port; + char *m_source_addr; + + time_t m_start_time; + int m_stream_ondemand; + int m_sync_time_set; + uint64_t m_sync_time_offset; + uint32_t m_rtptime_tickpersec; + double m_play_start_time; + // Receive thread variables + SDL_Thread *m_recv_thread; + + /************************************************************************* + * RTP variables - used to pass info to the bytestream + *************************************************************************/ + int m_rtp_ondemand; + int m_rtp_use_rtsp; + int m_rtp_media_number_in_session; + int m_rtp_buffering; + struct rtp *m_rtp_session; + CRtpByteStreamBase *m_rtp_byte_stream; + CMsgQueue m_rtp_msg_queue; + + rtp_packet *m_head, *m_tail; + uint32_t m_rtp_queue_len; + + // from rtsp... + int m_rtp_ssrc_set; + uint32_t m_rtp_ssrc; + int m_rtsp_base_ts_received; + uint32_t m_rtp_base_ts; + int m_rtsp_base_seq_received; + uint16_t m_rtp_base_seq; + + int determine_payload_type_from_rtp(void); + void create_rtp_byte_stream(uint8_t payload, uint64_t tps, format_list_t *fmt); + void clear_rtp_packets(void); + + // from rtcp, for broadcast, in case we get an RTCP before we determine + // the payload type + uint32_t m_rtcp_ntp_frac; + uint32_t m_rtcp_ntp_sec; + uint32_t m_rtcp_rtp_ts; + int m_rtcp_received; + + volatile int m_rtp_inited; + + /************************************************************************* + * Decoder thread variables + *************************************************************************/ + SDL_Thread *m_decode_thread; + volatile int m_decode_thread_waiting; + SDL_sem *m_decode_thread_sem; + + const codec_plugin_t *m_plugin; + codec_data_t *m_plugin_data; + + // State change variable + CMsgQueue m_decode_msg_queue; + // Private routines + int process_rtsp_transport(char *transport); + CPDPAudioSync *m_audio_sync; + CPDPVideoSync *m_video_sync; + void parse_decode_message(int &thread_stop, int &decoding); + COurInByteStream *m_byte_stream; + video_info_t *m_video_info; + audio_info_t *m_audio_info; + + const uint8_t *m_user_data; + int m_user_data_size; + +}; + +int pdp_process_rtsp_rtpinfo(char *rtpinfo, CPlayerSession *session, CPlayerMedia *media); + +extern audio_vft_t audio_vft; +extern video_vft_t video_vft; + +#define media_message(loglevel, fmt...) message(loglevel, "media", fmt) + +#endif diff --git a/include/pdp_mp4playersession.h b/include/pdp_mp4playersession.h new file mode 100644 index 0000000..5979aad --- /dev/null +++ b/include/pdp_mp4playersession.h @@ -0,0 +1,249 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2000, 2001. All Rights Reserved. + * + * Contributor(s): + * Bill May wmay@cisco.com + * video aspect ratio by: + * Peter Maersk-Moller peter @maersk-moller.net + * + * Adapted for PD/PDP by Yves Degoyon (ydegoyon@free.fr) + * + */ + +/* + * pdp_mp4playersession.h - provides definitions for a CPlayerSession. + * CPlayerSession is the base class that provides a combination audio/video + * stream/file playback. + * This class should be the main interface between any outside functionality + * and the player window. + */ + + +#ifndef __PDP_MP4PLAYERSESSION_H__ +#define __PDP_MP4PLAYERSESSION_H__ + +struct rtcp_sync_t; +typedef struct rtcp_sync_t rtcp_sync_t; + +#include +#include +#include "our_msg_queue.h" +#include "ip_port.h" +#include "pdp_mp4player~.h" + +class CPlayerMedia; +class CPDPAudioSync; +class CPDPVideoSync; + +typedef enum { + SESSION_PAUSED, + SESSION_BUFFERING, + SESSION_PLAYING, + SESSION_DONE +} session_state_t; + +typedef struct rtcp_sync_t { + uint64_t first_pak_ts; + uint64_t rtcp_ts; + uint32_t first_pak_rtp_ts; + uint32_t rtcp_rtp_ts; + uint64_t timescale; +} rtcp_sync_t; + +typedef void (*media_close_callback_f)(void *); + +class CPlayerSession { + public: + /* + * API routine - create player session. + */ + CPlayerSession(CMsgQueue *master_queue, + SDL_sem *master_sem, + const char *name, + t_pdp_mp4player *pdp_father); + /* + * API routine - destroy session - free all sub-structures, cleans + * up rtsp, etc + */ + ~CPlayerSession(); + /* + * API routine - create a rtsp session with the url. After that, you + * need to associate media + */ + int create_streaming_broadcast(session_desc_t *sdp, + char *ermsg, + uint32_t errlen); + int create_streaming_ondemand(const char *url, + char *errmsg, + uint32_t errlen, + int use_rtp_tcp); + /* + * API routine - play at time. If start_from_begin is FALSE, start_time + * and we're paused, it will continue from where it left off. + */ + int play_all_media(int start_from_begin = FALSE, double start_time = 0.0, + char *errmsg = NULL, uint32_t errlen = 0); + /* + * API routine - pause + */ + int pause_all_media(void); + /* + * API routine for media set up - associate a created + * media with the session. + */ + void add_media(CPlayerMedia *m); + /* + * API routine - returns sdp info for streamed session + */ + session_desc_t *get_sdp_info (void) { return m_sdp_info;} ; + rtsp_client_t *get_rtsp_client (void) { return m_rtsp_client; }; + /* + * API routine - after setting up media, need to set up sync thread + */ + void set_up_sync_thread(void); + CPDPVideoSync *set_up_video_sync(void); + CPDPAudioSync *set_up_audio_sync(void); + /* + * API routine - get the current time + */ + uint64_t get_playing_time (void) { + if (m_streaming && session_is_seekable() == 0) { + return (m_current_time - m_first_time_played); + } + return (m_current_time); + }; + /* + * API routine - get max play time + */ + double get_max_time (void); + /* + * Other API routines + */ + int session_has_audio(void); + int session_has_video(void); + void set_audio_volume(int volume); + int get_audio_volume(void) { return m_audio_volume; }; + void session_set_seekable (int seekable) { + m_seekable = seekable; + }; + int session_is_seekable (void) { + return (m_seekable); + }; + session_state_t get_session_state(void) { + return (m_session_state); + } + void set_media_close_callback (media_close_callback_f mccf, + void *mccd) { + m_media_close_callback = mccf; + m_media_close_callback_data = mccd; + } + int session_is_network (int &on_demand, int &rtp_over_rtsp) { + if (m_streaming == 0) { + return 0; + } + if (m_seekable) { + on_demand = 1; + rtp_over_rtsp = m_rtp_over_rtsp; + } else { + on_demand = 0; + rtp_over_rtsp = 0; + } + return 1; + } + /* + * Non-API routines - used for c interfaces, for sync task APIs. + */ + void wake_sync_thread (void) { + SDL_SemPost(m_sync_sem); + } + int send_sync_thread_a_message(uint32_t msgval, + unsigned char *msg = NULL, + uint32_t msg_len = 0) + { + return (m_sync_thread_msg_queue.send_message(msgval, msg, msg_len, m_sync_sem)); + }; + int sync_thread(int state); + uint64_t get_current_time(void); + void audio_is_ready (uint64_t latency, uint64_t time); + void adjust_start_time(int64_t delta); + int session_control_is_aggregate (void) { + return m_session_control_is_aggregate; + }; + void set_session_control (int is_aggregate) { + m_session_control_is_aggregate = is_aggregate; + } + CPlayerMedia *rtsp_url_to_media (const char *url); + int set_session_desc(int line, const char *desc); + const char *get_session_desc(int line); + void streaming_media_set_up(void) { m_streaming_media_set_up = 1; }; + CIpPort **get_unused_ip_port_ptr(void) { return &m_unused_ports; }; + void syncronize_rtp_bytestreams(rtcp_sync_t *sync); + private: + int process_msg_queue(int state); + int sync_thread_init(void); + int sync_thread_wait_sync(void); + int sync_thread_wait_audio(void); + int sync_thread_playing(void); + int sync_thread_paused(void); + int sync_thread_done(void); + const char *m_session_name; + const char *m_content_base; + int m_paused; + int m_streaming; + uint64_t m_current_time; // current time playing + uint64_t m_start; + uint64_t m_latency; + int m_clock_wrapped; + uint64_t m_play_start_time; + session_desc_t *m_sdp_info; + rtsp_client_t *m_rtsp_client; + CPlayerMedia *m_my_media; + CPDPAudioSync *m_audio_sync; + CPDPVideoSync *m_video_sync; + SDL_Thread *m_sync_thread; + SDL_sem *m_sync_sem; + CMsgQueue *m_master_msg_queue; + SDL_sem *m_master_msg_queue_sem; + CMsgQueue m_sync_thread_msg_queue; + range_desc_t *m_range; + int m_session_control_is_aggregate; + int m_waiting_for_audio; + int m_audio_volume; + int m_screen_scale; + int m_fullscreen; + int m_pixel_height; + int m_pixel_width; + int m_seekable; + volatile int m_sync_pause_done; + session_state_t m_session_state; + int m_hardware_error; + #define SESSION_DESC_COUNT 4 + const char *m_session_desc[SESSION_DESC_COUNT]; + media_close_callback_f m_media_close_callback; + void *m_media_close_callback_data; + int m_streaming_media_set_up; + CIpPort *m_unused_ports; + int m_rtp_over_rtsp; + uint64_t m_first_time_played; + bool m_have_audio_rtcp_sync; + rtcp_sync_t m_audio_rtcp_sync; + t_pdp_mp4player *m_father; +}; + +int pdp_sync_thread(void *data); + +#endif diff --git a/include/pdp_mp4player~.h b/include/pdp_mp4player~.h new file mode 100644 index 0000000..05e6d14 --- /dev/null +++ b/include/pdp_mp4player~.h @@ -0,0 +1,118 @@ + +#ifndef __PDP_MP4PLAYER__ +#define __PDP_MP4PLAYER__ + +struct pdp_mp4player_struct; +typedef struct pdp_mp4player_struct t_pdp_mp4player; + +#include "pdp.h" +#include "yuv.h" +#include +#include +#include +#include +#include +#include +#include +#include "pdp_mp4playersession.h" +#include "pdp_mp4playermedia.h" +#include "pdp_mp4videosync.h" +#include "pdp_mp4audiosync.h" +#include "media_utils.h" +#include "codec_plugin_private.h" +#include "our_config_file.h" +#include "player_util.h" +#include +#include + + +/* mpeg4ip includes taken from the source tree ( not exported ) */ +#include +#undef DECLARE_CONFIG_VARIABLES +#include "config_set.h" + +#undef CONFIG_BOOL +#define CONFIG_BOOL(var, name, defval) \ + { &(var), (name), CONFIG_TYPE_BOOL, (defval), (defval) } +#undef CONFIG_FLOAT +#define CONFIG_FLOAT(var, name, defval) \ + { &(var), (name), CONFIG_TYPE_FLOAT,(float) (defval), (float) (defval) } +#undef CONFIG_INT +#define CONFIG_INT(var, name, defval) \ + { &(var), (name), CONFIG_TYPE_INTEGER,(config_integer_t) (defval), (config_integer_t)(defval) } +#undef CONFIG_STRING +#define CONFIG_STRING(var, name, defval) \ + { &(var), (name), CONFIG_TYPE_STRING, (defval), (defval) } + +#include "pdp_mp4config.h" + +#undef DECLARE_CONFIG_VARIABLES +#ifndef debug_message +#define debug_message post +#endif +#include "rtp_transmitter.h" +#include "pdp_mp4videosource.h" +#include "pdp_mp4audiosource.h" + +#define DEFAULT_CHANNELS 1 +#define MIN_PRIORITY -20 +#define DEFAULT_PRIORITY 0 +#define MAX_PRIORITY 20 + +#define VIDEO_BUFFER_SIZE (1024*1024) +#define MAX_AUDIO_PACKET_SIZE (128 * 1024) +#define MIN_AUDIO_SIZE (64 * 1024) +#define AUDIO_PACKET_SIZE (2*1152) + +typedef struct pdp_mp4player_struct +{ + t_object x_obj; + t_float x_f; + + t_int x_packet0; + t_int x_dropped; + + t_pdp *x_header; + short int *x_data; + t_int x_vwidth; + t_int x_vheight; + t_int x_vsize; + + t_outlet *x_pdp_out; // output decoded pdp packets + t_outlet *x_outlet_left; // left audio output + t_outlet *x_outlet_right; // right audio output + t_outlet *x_outlet_streaming; // indicates the action of streaming + t_outlet *x_outlet_nbframes; // number of frames emitted + t_outlet *x_outlet_framerate; // real framerate + + char *x_url; + t_int x_rtpovertcp; // flag to bypass certain firewalls (tcp mode) + t_int x_streaming; // streaming flag + t_int x_nbframes; // number of frames emitted + t_int x_framerate; // framerate + t_int x_samplerate; // audio sample rate + t_int x_audiochannels; // audio channels + t_int x_audioon; // enough audio data to start playing + struct timeval x_starttime; // streaming starting time + t_int x_cursec; // current second + t_int x_secondcount; // number of frames received in the current second + pthread_t x_decodechild;// stream decoding thread + t_int x_priority; // priority of decoding thread + t_int x_newpicture; // flag indicating a new picture + + /* audio structures */ + t_int x_audio; // flag to activate the decoding of audio + short x_audio_buf[4*MAX_AUDIO_PACKET_SIZE]; /* buffer for audio from stream*/ + short x_audio_in[4*MAX_AUDIO_PACKET_SIZE]; /* buffer for resampled PCM audio */ + t_int x_audioin_position; // writing position for incoming audio + + /* mpeg4hippies structures */ + CPlayerSession *x_psession; + CMsgQueue x_queue; + SDL_sem *x_psem; + t_int x_decodingstate; // internal decoding state + +} t_pdp_mp4player; + +#endif + diff --git a/include/pdp_mp4rtpbytestream.h b/include/pdp_mp4rtpbytestream.h new file mode 100644 index 0000000..bc087ea --- /dev/null +++ b/include/pdp_mp4rtpbytestream.h @@ -0,0 +1,213 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2000, 2001. All Rights Reserved. + * + * Contributor(s): + * Bill May wmay@cisco.com + */ +/* + * player_rtp_bytestream.h - provides an RTP bytestream for the codecs + * to access + */ + +#ifndef __RTP_BYTESTREAM_H__ +#define __RTP_BYTESTREAM_H__ 1 +#include "our_bytestream.h" +#include "player_util.h" +#include "rtp/rtp.h" +#include +#include +#include + +class CRtpByteStreamBase : public COurInByteStream +{ + public: + CRtpByteStreamBase(const char *name, + format_list_t *fmt, + unsigned int rtp_pt, + int ondemand, + uint64_t tickpersec, + rtp_packet **head, + rtp_packet **tail, + int rtp_seq_set, + uint16_t rtp_base_seq, + int rtp_ts_set, + uint32_t rtp_base_ts, + int rtcp_received, + uint32_t ntp_frac, + uint32_t ntp_sec, + uint32_t rtp_ts); + + ~CRtpByteStreamBase(); + int eof (void) { return m_eof; }; + virtual void reset(void) { + player_debug_message("rtp bytestream reset"); + init(); + m_buffering = 0; + m_base_ts_set = 0; + m_rtp_base_seq_set = 0; + + }; + void set_skip_on_advance (uint32_t bytes_to_skip) { + m_skip_on_advance_bytes = bytes_to_skip; + }; + double get_max_playtime (void) { + if (m_fmt->media->media_range.have_range) { + return m_fmt->media->media_range.range_end; + } else if (m_fmt->media->parent->session_range.have_range) { + return m_fmt->media->parent->session_range.range_end; + } + return 0.0; + }; + + // various routines for RTP interface. + void set_rtp_base_ts(uint32_t t, uint64_t value = 0) { + m_base_ts_set = true; + m_base_rtp_ts = t; + m_base_ts = value; + }; + void set_rtp_base_seq(uint16_t s) { + m_rtp_base_seq_set = true; + m_rtp_base_seq = s; + }; + int can_skip_frame (void) { return 1; } ; + void set_wallclock_offset (uint64_t wclock, uint32_t rtp_ts); + int rtp_ready (void) { + return true; + }; + void recv_callback(struct rtp *session, rtp_event *e); + virtual void flush_rtp_packets(void); + int recv_task(int waiting); + uint32_t get_last_rtp_timestamp (void) {return m_rtptime_last; }; + void remove_packet_rtp_queue(rtp_packet *pak, int free); + void pause(void); + void set_sync(CPlayerSession *psptr); + + void syncronize(rtcp_sync_t *sync); + protected: + bool check_seq (uint16_t seq); + void set_last_seq(uint16_t seq); + void init(void); + // Make sure all classes call this to calculate real time. + uint64_t rtp_ts_to_msec(uint32_t rtp_ts, uint64_t uts, uint64_t &wrap_offset); + rtp_packet *m_head, *m_tail; + int m_offset_in_pak; + uint32_t m_skip_on_advance_bytes; + uint32_t m_ts; + uint64_t m_total; + bool m_base_ts_set; + uint32_t m_base_rtp_ts; + uint64_t m_base_ts; + bool m_rtp_base_seq_set; + uint16_t m_rtp_base_seq; + uint64_t m_timescale; + int m_stream_ondemand; + uint64_t m_wrap_offset; + bool m_rtcp_received; + uint64_t m_rtcp_ts; + uint32_t m_rtcp_rtp_ts; + uint64_t m_wallclock_offset_wrap; + void calculate_wallclock_offset_from_rtcp(uint32_t ntp_frac, + uint32_t ntp_sec, + uint32_t rtp_ts); + SDL_mutex *m_rtp_packet_mutex; + int m_buffering; + uint64_t m_rtp_buffer_time; + unsigned int m_rtp_pt; + virtual int check_rtp_frame_complete_for_payload_type(void); + virtual void rtp_done_buffering(void) {}; + uint32_t m_rtptime_last; + int m_recvd_pak; + int m_recvd_pak_timeout; + uint64_t m_recvd_pak_timeout_time; + uint64_t m_last_realtime; + format_list_t *m_fmt; + int m_eof; + int m_rtpinfo_set_from_pak; + uint16_t m_next_seq; + bool m_have_first_pak_ts; + uint64_t m_first_pak_ts; + uint32_t m_first_pak_rtp_ts; + CPlayerSession *m_psptr; + bool m_have_sync_info; + rtcp_sync_t m_sync_info; +}; + +class CRtpByteStream : public CRtpByteStreamBase +{ + public: + CRtpByteStream(const char *name, + format_list_t *fmt, + unsigned int rtp_pt, + int ondemand, + uint64_t tickpersec, + rtp_packet **head, + rtp_packet **tail, + int rtp_seq_set, + uint16_t rtp_base_seq, + int rtp_ts_set, + uint32_t rtp_base_ts, + int rtcp_received, + uint32_t ntp_frac, + uint32_t ntp_sec, + uint32_t rtp_ts); + ~CRtpByteStream(); + uint64_t start_next_frame(uint8_t **buffer, uint32_t *buflen, + void **userdata); + int skip_next_frame(uint64_t *ts, int *havesync, uint8_t **buffer, + uint32_t *buflen, void **userdata = NULL); + void used_bytes_for_frame(uint32_t bytes); + int have_no_data(void); + void flush_rtp_packets(void); + void reset(void); + protected: + uint8_t *m_buffer; + uint32_t m_buffer_len; + uint32_t m_buffer_len_max; + uint32_t m_bytes_used; +}; + +class CAudioRtpByteStream : public CRtpByteStream +{ + public: + CAudioRtpByteStream(unsigned int rtp_pt, + format_list_t *fmt, + int ondemand, + uint64_t tickpersec, + rtp_packet **head, + rtp_packet **tail, + int rtp_seq_set, + uint16_t rtp_base_seq, + int rtp_ts_set, + uint32_t rtp_base_ts, + int rtcp_received, + uint32_t ntp_frac, + uint32_t ntp_sec, + uint32_t rtp_ts); + ~CAudioRtpByteStream(); + int have_no_data(void); + int check_rtp_frame_complete_for_payload_type(void); + uint64_t start_next_frame(uint8_t **buffer, uint32_t *buflen, + void **userdata); + void reset(void); + private: + rtp_packet *m_working_pak; +}; +int add_rtp_packet_to_queue(rtp_packet *pak, + rtp_packet **head, + rtp_packet **tail, + const char *name); +#endif diff --git a/include/pdp_mp4videosource.h b/include/pdp_mp4videosource.h new file mode 100644 index 0000000..7433d33 --- /dev/null +++ b/include/pdp_mp4videosource.h @@ -0,0 +1,90 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2000, 2001. All Rights Reserved. + * + * Contributor(s): + * Dave Mackie dmackie@cisco.com + * Bill May wmay@cisco.com + * + * Adapted for PD/PDP by Yves Degoyon (ydegoyon@free.fr) + */ + +#ifndef __PDP_MP4VIDEOSOURCE__ +#define __PDP_MP4VIDEOSOURCE__ + +#include +#include +#include + +#include "media_source.h" +#include "video_encoder.h" + +class CPDPVideoSource : public CMediaSource { +public: + CPDPVideoSource() : CMediaSource() { + m_videoMap = NULL; + m_videoFrameMap = NULL; + } + + bool IsDone() { + return false; + } + + float GetProgress() { + return 0.0; + } + + void ProcessVideo(u_int8_t *pY, u_int8_t *pU, u_int8_t *pV); + + void DoStart(void); + + void DoStop(void); + +protected: + int ThreadMain(void); + + bool Init(void); + + int8_t StartTimeStamp(Timestamp &frameTimestamp); + + bool EndTimeStamp(int8_t frameNumber); + + Timestamp CalculateVideoTimestampFromFrames (uint64_t frame) { + double duration = frame; + duration *= TimestampTicks; + duration /= m_videoSrcFrameRate; + return m_videoCaptureStartTimestamp + (Timestamp)duration; + } +protected: + u_int8_t m_maxPasses; + + struct video_mbuf m_videoMbuf; + void* m_videoMap; + struct video_mmap* m_videoFrameMap; + Timestamp m_videoCaptureStartTimestamp; + uint64_t m_videoFrames; + Duration m_videoSrcFrameDuration; + int8_t m_captureHead; + int8_t m_encodeHead; + float m_videoSrcFrameRate; + uint64_t *m_videoFrameMapFrame; + Timestamp *m_videoFrameMapTimestamp; + uint64_t m_lastVideoFrameMapFrameLoaded; + Timestamp m_lastVideoFrameMapTimestampLoaded; + bool m_cacheTimestamp; +}; + +#endif /* __PDP_MP4VIDEOSOURCE__ */ diff --git a/include/pdp_mp4videosync.h b/include/pdp_mp4videosync.h new file mode 100644 index 0000000..a1bac85 --- /dev/null +++ b/include/pdp_mp4videosync.h @@ -0,0 +1,90 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2000, 2001. All Rights Reserved. + * + * Contributor(s): + * Bill May wmay@cisco.com + * video aspect ratio by: + * Peter Maersk-Moller peter@maersk-moller.net + * + * Adapted for PD/PDP by Yves Degoyon (ydegoyon@free.fr) + */ + +/* + * video.h - contains the interface class between the codec and the video + * display hardware. + */ + +#ifndef __PDP_MP4VIDEOSYNC__ +#define __PDP_MP4VIDEOSYNC__ + +#include "video.h" +#include "pdp_mp4player~.h" + +class CPDPVideoSync : public CVideoSync { + public: + CPDPVideoSync(CPlayerSession *psptr, t_pdp_mp4player *pdp_father); + ~CPDPVideoSync(void); + int initialize_video(const char *name); // from sync task + int is_video_ready(uint64_t &disptime); // from sync task + int64_t play_video_at(uint64_t current_time, // from sync task + int &have_eof); + int get_video_buffer(uint8_t **y, + uint8_t **u, + uint8_t **v); + void filled_video_buffers(uint64_t time); + void set_video_frame(const uint8_t *y, // from codec + const uint8_t *u, + const uint8_t *v, + int m_pixelw_y, + int m_pixelw_uv, + uint64_t time); + void config (int w, int h); // from codec + void set_wait_sem (SDL_sem *p) { m_decode_sem = p; }; // from set up + void flush_decode_buffers(void); // from decoder task in response to stop + void flush_sync_buffers(void); // from sync task in response to stop + void play_video(void); + private: + int m_video_bpp; + int m_video_scale; + int m_fullscreen; + unsigned int m_width, m_height; + int m_video_initialized; + int m_config_set; + int m_paused; + int m_double_width; + volatile int m_have_data; + SDL_Surface *m_screen; + SDL_Overlay *m_image; + SDL_Rect m_dstrect; + uint32_t m_fill_index, m_play_index; + int m_decode_waiting; + volatile int m_buffer_filled[MAX_VIDEO_BUFFERS]; + uint8_t *m_y_buffer[MAX_VIDEO_BUFFERS]; + uint8_t *m_u_buffer[MAX_VIDEO_BUFFERS]; + uint8_t *m_v_buffer[MAX_VIDEO_BUFFERS]; + uint64_t m_play_this_at[MAX_VIDEO_BUFFERS]; + int m_dont_fill; + int m_pixel_width; + int m_pixel_height; + int m_max_width; + int m_max_height; + t_pdp_mp4player *m_father; +}; + +CPDPVideoSync *pdp_create_video_sync(CPlayerSession *psptr, t_pdp_mp4player *pdp_father); + +#endif -- cgit v1.2.1