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@6603 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
parent
d8440f7c45
commit
b9f5453e29
@ -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
|
// Video codec types
|
||||||
enum VideoCodecType
|
enum VideoCodecType
|
||||||
{
|
{
|
||||||
kVideoCodecVP8,
|
kVideoCodecVP8,
|
||||||
|
kVideoCodecH264,
|
||||||
kVideoCodecI420,
|
kVideoCodecI420,
|
||||||
kVideoCodecRED,
|
kVideoCodecRED,
|
||||||
kVideoCodecULPFEC,
|
kVideoCodecULPFEC,
|
||||||
@ -601,6 +615,7 @@ enum VideoCodecType
|
|||||||
union VideoCodecUnion
|
union VideoCodecUnion
|
||||||
{
|
{
|
||||||
VideoCodecVP8 VP8;
|
VideoCodecVP8 VP8;
|
||||||
|
VideoCodecH264 H264;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -51,6 +51,7 @@
|
|||||||
|
|
||||||
#define VIDEOCODEC_I420
|
#define VIDEOCODEC_I420
|
||||||
#define VIDEOCODEC_VP8
|
#define VIDEOCODEC_VP8
|
||||||
|
#define VIDEOCODEC_H264
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// VoiceEngine
|
// VoiceEngine
|
||||||
|
@ -75,14 +75,22 @@ struct RTPVideoHeaderVP8 {
|
|||||||
bool beginningOfPartition; // True if this packet is the first
|
bool beginningOfPartition; // True if this packet is the first
|
||||||
// in a VP8 partition. Otherwise false
|
// in a VP8 partition. Otherwise false
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct RTPVideoHeaderH264 {
|
||||||
|
uint8_t nalu_header;
|
||||||
|
bool single_nalu;
|
||||||
|
};
|
||||||
|
|
||||||
union RTPVideoTypeHeader {
|
union RTPVideoTypeHeader {
|
||||||
RTPVideoHeaderVP8 VP8;
|
RTPVideoHeaderVP8 VP8;
|
||||||
|
RTPVideoHeaderH264 H264;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum RtpVideoCodecTypes {
|
enum RtpVideoCodecTypes {
|
||||||
kRtpVideoNone,
|
kRtpVideoNone,
|
||||||
kRtpVideoGeneric,
|
kRtpVideoGeneric,
|
||||||
kRtpVideoVp8
|
kRtpVideoVp8,
|
||||||
|
kRtpVideoH264
|
||||||
};
|
};
|
||||||
struct RTPVideoHeader {
|
struct RTPVideoHeader {
|
||||||
uint16_t width; // size
|
uint16_t width; // size
|
||||||
|
@ -434,6 +434,8 @@ class RTPPayloadVideoStrategy : public RTPPayloadStrategy {
|
|||||||
RtpVideoCodecTypes videoType = kRtpVideoGeneric;
|
RtpVideoCodecTypes videoType = kRtpVideoGeneric;
|
||||||
if (ModuleRTPUtility::StringCompare(payloadName, "VP8", 3)) {
|
if (ModuleRTPUtility::StringCompare(payloadName, "VP8", 3)) {
|
||||||
videoType = kRtpVideoVp8;
|
videoType = kRtpVideoVp8;
|
||||||
|
} else if (ModuleRTPUtility::StringCompare(payloadName, "H264", 4)) {
|
||||||
|
videoType = kRtpVideoH264;
|
||||||
} else if (ModuleRTPUtility::StringCompare(payloadName, "I420", 4)) {
|
} else if (ModuleRTPUtility::StringCompare(payloadName, "I420", 4)) {
|
||||||
videoType = kRtpVideoGeneric;
|
videoType = kRtpVideoGeneric;
|
||||||
} else if (ModuleRTPUtility::StringCompare(payloadName, "ULPFEC", 6)) {
|
} else if (ModuleRTPUtility::StringCompare(payloadName, "ULPFEC", 6)) {
|
||||||
|
@ -113,6 +113,8 @@ int32_t RTPReceiverVideo::ParseVideoCodecSpecific(
|
|||||||
return ReceiveGenericCodec(rtp_header, payload_data, payload_data_length);
|
return ReceiveGenericCodec(rtp_header, payload_data, payload_data_length);
|
||||||
case kRtpVideoVp8:
|
case kRtpVideoVp8:
|
||||||
return ReceiveVp8Codec(rtp_header, payload_data, payload_data_length);
|
return ReceiveVp8Codec(rtp_header, payload_data, payload_data_length);
|
||||||
|
case kRtpVideoH264:
|
||||||
|
assert(false); // Not yet supported.
|
||||||
case kRtpVideoNone:
|
case kRtpVideoNone:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -90,6 +90,8 @@ int32_t RTPSenderVideo::RegisterVideoPayload(
|
|||||||
RtpVideoCodecTypes videoType = kRtpVideoGeneric;
|
RtpVideoCodecTypes videoType = kRtpVideoGeneric;
|
||||||
if (ModuleRTPUtility::StringCompare(payloadName, "VP8",3)) {
|
if (ModuleRTPUtility::StringCompare(payloadName, "VP8",3)) {
|
||||||
videoType = kRtpVideoVp8;
|
videoType = kRtpVideoVp8;
|
||||||
|
} else if (ModuleRTPUtility::StringCompare(payloadName, "H264", 4)) {
|
||||||
|
videoType = kRtpVideoH264;
|
||||||
} else if (ModuleRTPUtility::StringCompare(payloadName, "I420", 4)) {
|
} else if (ModuleRTPUtility::StringCompare(payloadName, "I420", 4)) {
|
||||||
videoType = kRtpVideoGeneric;
|
videoType = kRtpVideoGeneric;
|
||||||
} else {
|
} else {
|
||||||
|
@ -40,6 +40,7 @@ namespace webrtc {
|
|||||||
#define VCM_ULPFEC_PAYLOAD_TYPE 97
|
#define VCM_ULPFEC_PAYLOAD_TYPE 97
|
||||||
#define VCM_VP8_PAYLOAD_TYPE 100
|
#define VCM_VP8_PAYLOAD_TYPE 100
|
||||||
#define VCM_I420_PAYLOAD_TYPE 124
|
#define VCM_I420_PAYLOAD_TYPE 124
|
||||||
|
#define VCM_H264_PAYLOAD_TYPE 127
|
||||||
|
|
||||||
enum VCMVideoProtection {
|
enum VCMVideoProtection {
|
||||||
kProtectionNack, // Both send-side and receive-side
|
kProtectionNack, // Both send-side and receive-side
|
||||||
|
@ -102,6 +102,30 @@ bool VCMCodecDataBase::Codec(int list_id,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
#endif
|
#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
|
#ifdef VIDEOCODEC_I420
|
||||||
case VCM_I420_IDX: {
|
case VCM_I420_IDX: {
|
||||||
strncpy(settings->plName, "I420", 5);
|
strncpy(settings->plName, "I420", 5);
|
||||||
@ -316,8 +340,7 @@ bool VCMCodecDataBase::RequiresEncoderReset(const VideoCodec& new_send_codec) {
|
|||||||
case kVideoCodecVP8:
|
case kVideoCodecVP8:
|
||||||
if (memcmp(&new_send_codec.codecSpecific.VP8,
|
if (memcmp(&new_send_codec.codecSpecific.VP8,
|
||||||
&send_codec_.codecSpecific.VP8,
|
&send_codec_.codecSpecific.VP8,
|
||||||
sizeof(new_send_codec.codecSpecific.VP8)) !=
|
sizeof(new_send_codec.codecSpecific.VP8)) != 0) {
|
||||||
0) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -327,6 +350,12 @@ bool VCMCodecDataBase::RequiresEncoderReset(const VideoCodec& new_send_codec) {
|
|||||||
case kVideoCodecI420:
|
case kVideoCodecI420:
|
||||||
case kVideoCodecRED:
|
case kVideoCodecRED:
|
||||||
case kVideoCodecULPFEC:
|
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;
|
break;
|
||||||
// Unknown codec type, reset just to be sure.
|
// Unknown codec type, reset just to be sure.
|
||||||
case kVideoCodecUnknown:
|
case kVideoCodecUnknown:
|
||||||
@ -619,6 +648,7 @@ VCMGenericDecoder* VCMCodecDataBase::CreateDecoder(VideoCodecType type) const {
|
|||||||
return new VCMGenericDecoder(*(new I420Decoder));
|
return new VCMGenericDecoder(*(new I420Decoder));
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
|
LOG(LS_WARNING) << "No internal decoder of this type exists.";
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -39,10 +39,15 @@ inline uint32_t MaskWord64ToUWord32(int64_t w64)
|
|||||||
#else
|
#else
|
||||||
#define VCM_VP8_IDX VCM_NO_CODEC_IDX
|
#define VCM_VP8_IDX VCM_NO_CODEC_IDX
|
||||||
#endif
|
#endif
|
||||||
#ifdef VIDEOCODEC_I420
|
#ifdef VIDEOCODEC_H264
|
||||||
#define VCM_I420_IDX VCM_VP8_IDX + 1
|
#define VCM_H264_IDX VCM_VP8_IDX + 1
|
||||||
#else
|
#else
|
||||||
#define VCM_I420_IDX VCM_VP8_IDX
|
#define VCM_H264_IDX VCM_VP8_IDX
|
||||||
|
#endif
|
||||||
|
#ifdef VIDEOCODEC_I420
|
||||||
|
#define VCM_I420_IDX VCM_H264_IDX + 1
|
||||||
|
#else
|
||||||
|
#define VCM_I420_IDX VCM_H264_IDX
|
||||||
#endif
|
#endif
|
||||||
#define VCM_NUM_VIDEO_CODECS_AVAILABLE VCM_I420_IDX + 1
|
#define VCM_NUM_VIDEO_CODECS_AVAILABLE VCM_I420_IDX + 1
|
||||||
|
|
||||||
|
@ -59,9 +59,13 @@ VideoCodec CreateDecoderVideoCodec(
|
|||||||
|
|
||||||
codec.plType = encoder_settings.payload_type;
|
codec.plType = encoder_settings.payload_type;
|
||||||
strcpy(codec.plName, encoder_settings.payload_name.c_str());
|
strcpy(codec.plName, encoder_settings.payload_name.c_str());
|
||||||
codec.codecType =
|
if (encoder_settings.payload_name == "VP8") {
|
||||||
(encoder_settings.payload_name == "VP8" ? kVideoCodecVP8
|
codec.codecType = kVideoCodecVP8;
|
||||||
: kVideoCodecGeneric);
|
} else if (encoder_settings.payload_name == "H264") {
|
||||||
|
codec.codecType = kVideoCodecH264;
|
||||||
|
} else {
|
||||||
|
codec.codecType = kVideoCodecGeneric;
|
||||||
|
}
|
||||||
|
|
||||||
if (codec.codecType == kVideoCodecVP8) {
|
if (codec.codecType == kVideoCodecVP8) {
|
||||||
codec.codecSpecific.VP8.resilience = kResilientStream;
|
codec.codecSpecific.VP8.resilience = kResilientStream;
|
||||||
@ -73,6 +77,12 @@ VideoCodec CreateDecoderVideoCodec(
|
|||||||
codec.codecSpecific.VP8.keyFrameInterval = 3000;
|
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.width = 320;
|
||||||
codec.height = 180;
|
codec.height = 180;
|
||||||
codec.startBitrate = codec.minBitrate = codec.maxBitrate = 300;
|
codec.startBitrate = codec.minBitrate = codec.maxBitrate = 300;
|
||||||
|
@ -48,6 +48,9 @@ size_t StartBitrate() { return static_cast<size_t>(FLAGS_start_bitrate); }
|
|||||||
|
|
||||||
DEFINE_int32(max_bitrate, 800, "Maximum video bitrate.");
|
DEFINE_int32(max_bitrate, 800, "Maximum video bitrate.");
|
||||||
size_t MaxBitrate() { return static_cast<size_t>(FLAGS_max_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
|
} // namespace flags
|
||||||
|
|
||||||
static const uint32_t kSendSsrc = 0x654321;
|
static const uint32_t kSendSsrc = 0x654321;
|
||||||
@ -72,10 +75,16 @@ void Loopback() {
|
|||||||
send_config.rtp.ssrcs.push_back(kSendSsrc);
|
send_config.rtp.ssrcs.push_back(kSendSsrc);
|
||||||
|
|
||||||
send_config.local_renderer = local_preview.get();
|
send_config.local_renderer = local_preview.get();
|
||||||
|
scoped_ptr<VideoEncoder> encoder;
|
||||||
scoped_ptr<VP8Encoder> encoder(VP8Encoder::Create());
|
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.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;
|
send_config.encoder_settings.payload_type = 124;
|
||||||
std::vector<VideoStream> video_streams = test::CreateVideoStreams(1);
|
std::vector<VideoStream> video_streams = test::CreateVideoStreams(1);
|
||||||
VideoStream* stream = &video_streams[0];
|
VideoStream* stream = &video_streams[0];
|
||||||
|
@ -101,6 +101,9 @@ void ViEAutoTest::PrintVideoCodec(const webrtc::VideoCodec videoCodec)
|
|||||||
case webrtc::kVideoCodecI420:
|
case webrtc::kVideoCodecI420:
|
||||||
ViETest::Log("\tcodecType: I420");
|
ViETest::Log("\tcodecType: I420");
|
||||||
break;
|
break;
|
||||||
|
case webrtc::kVideoCodecH264:
|
||||||
|
ViETest::Log("\tcodecType: H264");
|
||||||
|
break;
|
||||||
case webrtc::kVideoCodecRED:
|
case webrtc::kVideoCodecRED:
|
||||||
ViETest::Log("\tcodecType: RED");
|
ViETest::Log("\tcodecType: RED");
|
||||||
break;
|
break;
|
||||||
|
@ -69,6 +69,18 @@ static void LogCodec(const VideoCodec& codec) {
|
|||||||
<< ", qp max "
|
<< ", qp max "
|
||||||
<< codec.simulcastStream[idx].qpMax;
|
<< 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 &&
|
} else if ((video_codec.codecType == kVideoCodecVP8 &&
|
||||||
strncmp(video_codec.plName, "VP8", 4) == 0) ||
|
strncmp(video_codec.plName, "VP8", 4) == 0) ||
|
||||||
(video_codec.codecType == kVideoCodecI420 &&
|
(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.
|
// OK.
|
||||||
} else if (video_codec.codecType != kVideoCodecGeneric) {
|
} else if (video_codec.codecType != kVideoCodecGeneric) {
|
||||||
LOG(LS_ERROR) << "Codec type and name mismatch.";
|
LOG(LS_ERROR) << "Codec type and name mismatch.";
|
||||||
|
Loading…
x
Reference in New Issue
Block a user