diff options
author | stefan@webrtc.org <stefan@webrtc.org@4adac7df-926f-26a2-2b94-8c16560cd09d> | 2014-07-04 12:42:07 +0000 |
---|---|---|
committer | stefan@webrtc.org <stefan@webrtc.org@4adac7df-926f-26a2-2b94-8c16560cd09d> | 2014-07-04 12:42:07 +0000 |
commit | 2d4a80c05adffe07b48dc235475852450cd90568 (patch) | |
tree | 8be3d90f488a107bac7e54dbecc02ffea78c231e | |
parent | 65afbf3e1da598f94f47eb0c11fe2b668e4f30f4 (diff) | |
download | webrtc-2d4a80c05adffe07b48dc235475852450cd90568.tar.gz |
Add boilerplate code for H.264.
R=mflodman@webrtc.org, niklas.enbom@webrtc.org
Review URL: https://webrtc-codereview.appspot.com/17849005
git-svn-id: http://webrtc.googlecode.com/svn/trunk/webrtc@6603 4adac7df-926f-26a2-2b94-8c16560cd09d
-rw-r--r-- | common_types.h | 15 | ||||
-rw-r--r-- | engine_configurations.h | 1 | ||||
-rw-r--r-- | modules/interface/module_common_types.h | 10 | ||||
-rw-r--r-- | modules/rtp_rtcp/source/rtp_payload_registry.cc | 2 | ||||
-rw-r--r-- | modules/rtp_rtcp/source/rtp_receiver_video.cc | 2 | ||||
-rw-r--r-- | modules/rtp_rtcp/source/rtp_sender_video.cc | 2 | ||||
-rw-r--r-- | modules/video_coding/main/interface/video_coding_defines.h | 1 | ||||
-rw-r--r-- | modules/video_coding/main/source/codec_database.cc | 34 | ||||
-rw-r--r-- | modules/video_coding/main/source/internal_defines.h | 9 | ||||
-rw-r--r-- | test/encoder_settings.cc | 16 | ||||
-rw-r--r-- | video/loopback.cc | 15 | ||||
-rw-r--r-- | video_engine/test/auto_test/source/vie_autotest.cc | 3 | ||||
-rw-r--r-- | video_engine/vie_codec_impl.cc | 16 |
13 files changed, 114 insertions, 12 deletions
diff --git a/common_types.h b/common_types.h index 6892a83f..193e2818 100644 --- a/common_types.h +++ b/common_types.h @@ -587,10 +587,24 @@ struct VideoCodecVP8 { } }; +// H264 specific. +struct VideoCodecH264 +{ + VideoCodecProfile profile; + bool frameDroppingOn; + int keyFrameInterval; + // These are NULL/0 if not externally negotiated. + const uint8_t* spsData; + size_t spsLen; + const uint8_t* ppsData; + size_t ppsLen; +}; + // Video codec types enum VideoCodecType { kVideoCodecVP8, + kVideoCodecH264, kVideoCodecI420, kVideoCodecRED, kVideoCodecULPFEC, @@ -601,6 +615,7 @@ enum VideoCodecType union VideoCodecUnion { VideoCodecVP8 VP8; + VideoCodecH264 H264; }; diff --git a/engine_configurations.h b/engine_configurations.h index be858b8e..e9f23097 100644 --- a/engine_configurations.h +++ b/engine_configurations.h @@ -51,6 +51,7 @@ #define VIDEOCODEC_I420 #define VIDEOCODEC_VP8 +#define VIDEOCODEC_H264 // ============================================================================ // VoiceEngine diff --git a/modules/interface/module_common_types.h b/modules/interface/module_common_types.h index 2c947071..e37313c9 100644 --- a/modules/interface/module_common_types.h +++ b/modules/interface/module_common_types.h @@ -75,14 +75,22 @@ struct RTPVideoHeaderVP8 { bool beginningOfPartition; // True if this packet is the first // in a VP8 partition. Otherwise false }; + +struct RTPVideoHeaderH264 { + uint8_t nalu_header; + bool single_nalu; +}; + union RTPVideoTypeHeader { RTPVideoHeaderVP8 VP8; + RTPVideoHeaderH264 H264; }; enum RtpVideoCodecTypes { kRtpVideoNone, kRtpVideoGeneric, - kRtpVideoVp8 + kRtpVideoVp8, + kRtpVideoH264 }; struct RTPVideoHeader { uint16_t width; // size diff --git a/modules/rtp_rtcp/source/rtp_payload_registry.cc b/modules/rtp_rtcp/source/rtp_payload_registry.cc index db2e4cd3..26db8f32 100644 --- a/modules/rtp_rtcp/source/rtp_payload_registry.cc +++ b/modules/rtp_rtcp/source/rtp_payload_registry.cc @@ -434,6 +434,8 @@ class RTPPayloadVideoStrategy : public RTPPayloadStrategy { RtpVideoCodecTypes videoType = kRtpVideoGeneric; if (ModuleRTPUtility::StringCompare(payloadName, "VP8", 3)) { videoType = kRtpVideoVp8; + } else if (ModuleRTPUtility::StringCompare(payloadName, "H264", 4)) { + videoType = kRtpVideoH264; } else if (ModuleRTPUtility::StringCompare(payloadName, "I420", 4)) { videoType = kRtpVideoGeneric; } else if (ModuleRTPUtility::StringCompare(payloadName, "ULPFEC", 6)) { diff --git a/modules/rtp_rtcp/source/rtp_receiver_video.cc b/modules/rtp_rtcp/source/rtp_receiver_video.cc index 5bb519f6..26159916 100644 --- a/modules/rtp_rtcp/source/rtp_receiver_video.cc +++ b/modules/rtp_rtcp/source/rtp_receiver_video.cc @@ -113,6 +113,8 @@ int32_t RTPReceiverVideo::ParseVideoCodecSpecific( return ReceiveGenericCodec(rtp_header, payload_data, payload_data_length); case kRtpVideoVp8: return ReceiveVp8Codec(rtp_header, payload_data, payload_data_length); + case kRtpVideoH264: + assert(false); // Not yet supported. case kRtpVideoNone: break; } diff --git a/modules/rtp_rtcp/source/rtp_sender_video.cc b/modules/rtp_rtcp/source/rtp_sender_video.cc index 5d8ae166..e4138ff5 100644 --- a/modules/rtp_rtcp/source/rtp_sender_video.cc +++ b/modules/rtp_rtcp/source/rtp_sender_video.cc @@ -90,6 +90,8 @@ int32_t RTPSenderVideo::RegisterVideoPayload( RtpVideoCodecTypes videoType = kRtpVideoGeneric; if (ModuleRTPUtility::StringCompare(payloadName, "VP8",3)) { videoType = kRtpVideoVp8; + } else if (ModuleRTPUtility::StringCompare(payloadName, "H264", 4)) { + videoType = kRtpVideoH264; } else if (ModuleRTPUtility::StringCompare(payloadName, "I420", 4)) { videoType = kRtpVideoGeneric; } else { diff --git a/modules/video_coding/main/interface/video_coding_defines.h b/modules/video_coding/main/interface/video_coding_defines.h index fab91afd..c5f93cb1 100644 --- a/modules/video_coding/main/interface/video_coding_defines.h +++ b/modules/video_coding/main/interface/video_coding_defines.h @@ -40,6 +40,7 @@ namespace webrtc { #define VCM_ULPFEC_PAYLOAD_TYPE 97 #define VCM_VP8_PAYLOAD_TYPE 100 #define VCM_I420_PAYLOAD_TYPE 124 +#define VCM_H264_PAYLOAD_TYPE 127 enum VCMVideoProtection { kProtectionNack, // Both send-side and receive-side diff --git a/modules/video_coding/main/source/codec_database.cc b/modules/video_coding/main/source/codec_database.cc index e7a9d91b..7e26bea4 100644 --- a/modules/video_coding/main/source/codec_database.cc +++ b/modules/video_coding/main/source/codec_database.cc @@ -102,6 +102,30 @@ bool VCMCodecDataBase::Codec(int list_id, return true; } #endif +#ifdef VIDEOCODEC_H264 + case VCM_H264_IDX: { + strncpy(settings->plName, "H264", 5); + settings->codecType = kVideoCodecH264; + // 96 to 127 dynamic payload types for video codecs. + settings->plType = VCM_H264_PAYLOAD_TYPE; + settings->startBitrate = 100; + settings->minBitrate = VCM_MIN_BITRATE; + settings->maxBitrate = 0; + settings->maxFramerate = VCM_DEFAULT_FRAME_RATE; + settings->width = VCM_DEFAULT_CODEC_WIDTH; + settings->height = VCM_DEFAULT_CODEC_HEIGHT; + settings->numberOfSimulcastStreams = 0; + settings->qpMax = 56; + settings->codecSpecific.H264.profile = kProfileBase; + settings->codecSpecific.H264.frameDroppingOn = true; + settings->codecSpecific.H264.keyFrameInterval = 3000; + settings->codecSpecific.H264.spsData = NULL; + settings->codecSpecific.H264.spsLen = 0; + settings->codecSpecific.H264.ppsData = NULL; + settings->codecSpecific.H264.ppsLen = 0; + return true; + } +#endif #ifdef VIDEOCODEC_I420 case VCM_I420_IDX: { strncpy(settings->plName, "I420", 5); @@ -316,8 +340,7 @@ bool VCMCodecDataBase::RequiresEncoderReset(const VideoCodec& new_send_codec) { case kVideoCodecVP8: if (memcmp(&new_send_codec.codecSpecific.VP8, &send_codec_.codecSpecific.VP8, - sizeof(new_send_codec.codecSpecific.VP8)) != - 0) { + sizeof(new_send_codec.codecSpecific.VP8)) != 0) { return true; } break; @@ -327,6 +350,12 @@ bool VCMCodecDataBase::RequiresEncoderReset(const VideoCodec& new_send_codec) { case kVideoCodecI420: case kVideoCodecRED: case kVideoCodecULPFEC: + case kVideoCodecH264: + if (memcmp(&new_send_codec.codecSpecific.H264, + &send_codec_.codecSpecific.H264, + sizeof(new_send_codec.codecSpecific.H264)) != 0) { + return true; + } break; // Unknown codec type, reset just to be sure. case kVideoCodecUnknown: @@ -619,6 +648,7 @@ VCMGenericDecoder* VCMCodecDataBase::CreateDecoder(VideoCodecType type) const { return new VCMGenericDecoder(*(new I420Decoder)); #endif default: + LOG(LS_WARNING) << "No internal decoder of this type exists."; return NULL; } } diff --git a/modules/video_coding/main/source/internal_defines.h b/modules/video_coding/main/source/internal_defines.h index efc6d8dd..1128312b 100644 --- a/modules/video_coding/main/source/internal_defines.h +++ b/modules/video_coding/main/source/internal_defines.h @@ -39,10 +39,15 @@ inline uint32_t MaskWord64ToUWord32(int64_t w64) #else #define VCM_VP8_IDX VCM_NO_CODEC_IDX #endif +#ifdef VIDEOCODEC_H264 + #define VCM_H264_IDX VCM_VP8_IDX + 1 +#else + #define VCM_H264_IDX VCM_VP8_IDX +#endif #ifdef VIDEOCODEC_I420 - #define VCM_I420_IDX VCM_VP8_IDX + 1 + #define VCM_I420_IDX VCM_H264_IDX + 1 #else - #define VCM_I420_IDX VCM_VP8_IDX + #define VCM_I420_IDX VCM_H264_IDX #endif #define VCM_NUM_VIDEO_CODECS_AVAILABLE VCM_I420_IDX + 1 diff --git a/test/encoder_settings.cc b/test/encoder_settings.cc index 5193be65..9842d1ed 100644 --- a/test/encoder_settings.cc +++ b/test/encoder_settings.cc @@ -59,9 +59,13 @@ VideoCodec CreateDecoderVideoCodec( codec.plType = encoder_settings.payload_type; strcpy(codec.plName, encoder_settings.payload_name.c_str()); - codec.codecType = - (encoder_settings.payload_name == "VP8" ? kVideoCodecVP8 - : kVideoCodecGeneric); + if (encoder_settings.payload_name == "VP8") { + codec.codecType = kVideoCodecVP8; + } else if (encoder_settings.payload_name == "H264") { + codec.codecType = kVideoCodecH264; + } else { + codec.codecType = kVideoCodecGeneric; + } if (codec.codecType == kVideoCodecVP8) { codec.codecSpecific.VP8.resilience = kResilientStream; @@ -73,6 +77,12 @@ VideoCodec CreateDecoderVideoCodec( codec.codecSpecific.VP8.keyFrameInterval = 3000; } + if (codec.codecType == kVideoCodecH264) { + codec.codecSpecific.H264.profile = kProfileBase; + codec.codecSpecific.H264.frameDroppingOn = true; + codec.codecSpecific.H264.keyFrameInterval = 3000; + } + codec.width = 320; codec.height = 180; codec.startBitrate = codec.minBitrate = codec.maxBitrate = 300; diff --git a/video/loopback.cc b/video/loopback.cc index ea65ebb4..276f1d45 100644 --- a/video/loopback.cc +++ b/video/loopback.cc @@ -48,6 +48,9 @@ size_t StartBitrate() { return static_cast<size_t>(FLAGS_start_bitrate); } DEFINE_int32(max_bitrate, 800, "Maximum video bitrate."); size_t MaxBitrate() { return static_cast<size_t>(FLAGS_max_bitrate); } + +DEFINE_string(codec, "VP8", "Video codec to use."); +std::string Codec() { return static_cast<std::string>(FLAGS_codec); } } // namespace flags static const uint32_t kSendSsrc = 0x654321; @@ -72,10 +75,16 @@ void Loopback() { send_config.rtp.ssrcs.push_back(kSendSsrc); send_config.local_renderer = local_preview.get(); - - scoped_ptr<VP8Encoder> encoder(VP8Encoder::Create()); + scoped_ptr<VideoEncoder> encoder; + if (flags::Codec() == "VP8") { + encoder.reset(VP8Encoder::Create()); + } else { + // Codec not supported. + assert(false && "Codec not supported!"); + return; + } send_config.encoder_settings.encoder = encoder.get(); - send_config.encoder_settings.payload_name = "VP8"; + send_config.encoder_settings.payload_name = flags::Codec(); send_config.encoder_settings.payload_type = 124; std::vector<VideoStream> video_streams = test::CreateVideoStreams(1); VideoStream* stream = &video_streams[0]; diff --git a/video_engine/test/auto_test/source/vie_autotest.cc b/video_engine/test/auto_test/source/vie_autotest.cc index 188567cb..fb1a46f2 100644 --- a/video_engine/test/auto_test/source/vie_autotest.cc +++ b/video_engine/test/auto_test/source/vie_autotest.cc @@ -101,6 +101,9 @@ void ViEAutoTest::PrintVideoCodec(const webrtc::VideoCodec videoCodec) case webrtc::kVideoCodecI420: ViETest::Log("\tcodecType: I420"); break; + case webrtc::kVideoCodecH264: + ViETest::Log("\tcodecType: H264"); + break; case webrtc::kVideoCodecRED: ViETest::Log("\tcodecType: RED"); break; diff --git a/video_engine/vie_codec_impl.cc b/video_engine/vie_codec_impl.cc index 3ba56de5..050958e2 100644 --- a/video_engine/vie_codec_impl.cc +++ b/video_engine/vie_codec_impl.cc @@ -69,6 +69,18 @@ static void LogCodec(const VideoCodec& codec) { << ", qp max " << codec.simulcastStream[idx].qpMax; } + } else if (codec.codecType == kVideoCodecH264) { + LOG(LS_INFO) << "H264 specific settings"; + LOG(LS_INFO) << "profile: " + << codec.codecSpecific.H264.profile + << ", framedropping: " + << codec.codecSpecific.H264.frameDroppingOn + << ", keyFrameInterval: " + << codec.codecSpecific.H264.keyFrameInterval + << ", spslen: " + << codec.codecSpecific.H264.spsLen + << ", ppslen: " + << codec.codecSpecific.H264.ppsLen; } } @@ -629,7 +641,9 @@ bool ViECodecImpl::CodecValid(const VideoCodec& video_codec) { } else if ((video_codec.codecType == kVideoCodecVP8 && strncmp(video_codec.plName, "VP8", 4) == 0) || (video_codec.codecType == kVideoCodecI420 && - strncmp(video_codec.plName, "I420", 4) == 0)) { + strncmp(video_codec.plName, "I420", 4) == 0) || + (video_codec.codecType == kVideoCodecH264 && + strncmp(video_codec.plName, "H264", 4) == 0)) { // OK. } else if (video_codec.codecType != kVideoCodecGeneric) { LOG(LS_ERROR) << "Codec type and name mismatch."; |