Skip to content

Commit

Permalink
Updates vp8 picture id when switching spatial qualities (#962)
Browse files Browse the repository at this point in the history
  • Loading branch information
jcague authored Jul 13, 2017
1 parent 1a1e988 commit 1bb1dca
Show file tree
Hide file tree
Showing 6 changed files with 72 additions and 11 deletions.
8 changes: 5 additions & 3 deletions erizo/src/erizo/MediaDefinitions.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,19 +24,19 @@ struct dataPacket {

dataPacket(int comp_, const char *data_, int length_, packetType type_, uint64_t received_time_ms_) :
comp{comp_}, length{length_}, type{type_}, received_time_ms{received_time_ms_}, is_keyframe{false},
ending_of_layer_frame{false} {
ending_of_layer_frame{false}, picture_id{-1} {
memcpy(data, data_, length_);
}

dataPacket(int comp_, const char *data_, int length_, packetType type_) :
comp{comp_}, length{length_}, type{type_}, received_time_ms{ClockUtils::timePointToMs(clock::now())},
is_keyframe{false}, ending_of_layer_frame{false} {
is_keyframe{false}, ending_of_layer_frame{false}, picture_id{-1} {
memcpy(data, data_, length_);
}

dataPacket(int comp_, const unsigned char *data_, int length_) :
comp{comp_}, length{length_}, type{VIDEO_PACKET}, received_time_ms{ClockUtils::timePointToMs(clock::now())},
is_keyframe{false}, ending_of_layer_frame{false} {
is_keyframe{false}, ending_of_layer_frame{false}, picture_id{-1} {
memcpy(data, data_, length_);
}

Expand Down Expand Up @@ -65,6 +65,8 @@ struct dataPacket {
std::vector<int> compatible_temporal_layers;
bool is_keyframe; // Note: It can be just a keyframe first packet in VP8
bool ending_of_layer_frame;
int picture_id;
std::string codec;
};

class Monitor {
Expand Down
6 changes: 5 additions & 1 deletion erizo/src/erizo/rtp/LayerDetectorHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,10 @@ void LayerDetectorHandler::read(Context *ctx, std::shared_ptr<dataPacket> packet
RtpHeader *rtp_header = reinterpret_cast<RtpHeader*>(packet->data);
RtpMap *codec = connection_->getRemoteSdpInfo().getCodecByExternalPayloadType(rtp_header->getPayloadType());
if (codec && codec->encoding_name == "VP8") {
packet->codec = "VP8";
parseLayerInfoFromVP8(packet);
} else if (codec && codec->encoding_name == "VP9") {
packet->codec = "VP9";
parseLayerInfoFromVP9(packet);
}
}
Expand All @@ -48,7 +50,9 @@ void LayerDetectorHandler::parseLayerInfoFromVP8(std::shared_ptr<dataPacket> pac
start_buffer = start_buffer + rtp_header->getHeaderLength();
RTPPayloadVP8* payload = vp8_parser_.parseVP8(
start_buffer, packet->length - rtp_header->getHeaderLength());

if (payload->hasPictureID) {
packet->picture_id = payload->pictureID;
}
packet->compatible_temporal_layers = {};
switch (payload->tID) {
case 0:
Expand Down
26 changes: 22 additions & 4 deletions erizo/src/erizo/rtp/QualityFilterHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "./WebRtcConnection.h"
#include "lib/ClockUtils.h"
#include "rtp/RtpUtils.h"
#include "rtp/RtpVP8Parser.h"

namespace erizo {

Expand All @@ -16,7 +17,8 @@ QualityFilterHandler::QualityFilterHandler()
target_spatial_layer_{0},
future_spatial_layer_{-1}, target_temporal_layer_{0},
video_sink_ssrc_{0}, video_source_ssrc_{0}, last_ssrc_received_{0},
max_video_bw_{0}, last_timestamp_sent_{0}, timestamp_offset_{0}, time_change_started_{clock::now()} {}
max_video_bw_{0}, last_timestamp_sent_{0}, timestamp_offset_{0},
time_change_started_{clock::now()}, picture_id_offset_{0}, last_picture_id_sent_{0} {}

void QualityFilterHandler::enable() {
enabled_ = true;
Expand All @@ -26,7 +28,7 @@ void QualityFilterHandler::disable() {
enabled_ = false;
}

void QualityFilterHandler::handleFeedbackPackets(std::shared_ptr<dataPacket> packet) {
void QualityFilterHandler::handleFeedbackPackets(const std::shared_ptr<dataPacket> &packet) {
RtpUtils::forEachRRBlock(packet, [this](RtcpHeader *chead) {
if (chead->packettype == RTCP_PS_Feedback_PT &&
(chead->getBlockCount() == RTCP_PLI_FMT ||
Expand Down Expand Up @@ -72,7 +74,7 @@ void QualityFilterHandler::sendPLI() {
getContext()->fireRead(RtpUtils::createPLI(video_sink_ssrc_, video_source_ssrc_));
}

void QualityFilterHandler::changeSpatialLayerOnKeyframeReceived(std::shared_ptr<dataPacket> packet) {
void QualityFilterHandler::changeSpatialLayerOnKeyframeReceived(const std::shared_ptr<dataPacket> &packet) {
if (future_spatial_layer_ == -1) {
return;
}
Expand All @@ -91,7 +93,7 @@ void QualityFilterHandler::changeSpatialLayerOnKeyframeReceived(std::shared_ptr<
}
}

void QualityFilterHandler::detectVideoScalability(std::shared_ptr<dataPacket> packet) {
void QualityFilterHandler::detectVideoScalability(const std::shared_ptr<dataPacket> &packet) {
if (is_scalable_ || packet->type != VIDEO_PACKET) {
return;
}
Expand All @@ -101,6 +103,15 @@ void QualityFilterHandler::detectVideoScalability(std::shared_ptr<dataPacket> pa
}
}

void QualityFilterHandler::updatePictureID(const std::shared_ptr<dataPacket> &packet) {
if (packet->codec == "VP8") {
RtpHeader *rtp_header = reinterpret_cast<RtpHeader*>(packet->data);
unsigned char* start_buffer = reinterpret_cast<unsigned char*> (packet->data);
start_buffer = start_buffer + rtp_header->getHeaderLength();
RtpVP8Parser::setVP8PictureID(start_buffer, packet->length - rtp_header->getHeaderLength(), last_picture_id_sent_);
}
}

void QualityFilterHandler::write(Context *ctx, std::shared_ptr<dataPacket> packet) {
RtcpHeader *chead = reinterpret_cast<RtcpHeader*>(packet->data);

Expand All @@ -113,6 +124,7 @@ void QualityFilterHandler::write(Context *ctx, std::shared_ptr<dataPacket> packe

uint32_t ssrc = rtp_header->getSSRC();
uint16_t sequence_number = rtp_header->getSeqNumber();
int picture_id = packet->picture_id;

if (last_ssrc_received_ != 0 && ssrc != last_ssrc_received_) {
receiving_multiple_ssrc_ = true;
Expand All @@ -134,6 +146,9 @@ void QualityFilterHandler::write(Context *ctx, std::shared_ptr<dataPacket> packe
if (last_timestamp_sent_ > 0) {
timestamp_offset_ = last_timestamp_sent_ - new_timestamp + 1;
}
if (last_picture_id_sent_ > 0) {
picture_id_offset_ = last_picture_id_sent_ - picture_id + 1;
}
}

if (!packet->belongsToTemporalLayer(target_temporal_layer_)) {
Expand All @@ -155,6 +170,9 @@ void QualityFilterHandler::write(Context *ctx, std::shared_ptr<dataPacket> packe

last_timestamp_sent_ = new_timestamp + timestamp_offset_;
rtp_header->setTimestamp(last_timestamp_sent_);

last_picture_id_sent_ = picture_id + picture_id_offset_;
updatePictureID(packet);
}

// TODO(javier): Handle SRs and translate Sequence Numbers?
Expand Down
9 changes: 6 additions & 3 deletions erizo/src/erizo/rtp/QualityFilterHandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,11 @@ class QualityFilterHandler: public Handler, public std::enable_shared_from_this<
private:
void sendPLI();
void checkLayers();
void handleFeedbackPackets(std::shared_ptr<dataPacket> packet);
void handleFeedbackPackets(const std::shared_ptr<dataPacket> &packet);
bool checkSSRCChange(uint32_t ssrc);
void changeSpatialLayerOnKeyframeReceived(std::shared_ptr<dataPacket> packet);
void detectVideoScalability(std::shared_ptr<dataPacket> packet);
void changeSpatialLayerOnKeyframeReceived(const std::shared_ptr<dataPacket> &packet);
void detectVideoScalability(const std::shared_ptr<dataPacket> &packet);
void updatePictureID(const std::shared_ptr<dataPacket> &packet);

private:
std::shared_ptr<QualityManager> quality_manager_;
Expand All @@ -61,6 +62,8 @@ class QualityFilterHandler: public Handler, public std::enable_shared_from_this<
uint32_t last_timestamp_sent_;
uint32_t timestamp_offset_;
time_point time_change_started_;
int picture_id_offset_;
int last_picture_id_sent_;
};
} // namespace erizo

Expand Down
33 changes: 33 additions & 0 deletions erizo/src/erizo/rtp/RtpVP8Parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,39 @@ int ParseVP8Extension(erizo::RTPPayloadVP8* vp8, const unsigned char* dataPtr, i
return parsedBytes;
}

void RtpVP8Parser::setVP8PictureID(unsigned char* data, int data_length, int picture_id) {
unsigned char* data_ptr = data;

bool extension = (*data_ptr & 0x80) ? true : false; // X bit

data_ptr++;
data_length--;

if (extension) {
if (data_length <= 0) {
return;
}
bool has_picture_id = (*data_ptr & 0x80) ? true : false; // I bit
data_ptr++;
data_length--;

if (has_picture_id) {
if (data_length <= 0) {
return;
}
const uint16_t pic_id = static_cast<uint16_t> (picture_id);
int picture_id_len = (*data_ptr & 0x80) ? 2 : 1;
if (picture_id_len > data_length) return;
if (picture_id_len == 2) {
data_ptr[0] = 0x80 | ((pic_id >> 8) & 0x7F);
data_ptr[1] = pic_id & 0xFF;
} else if (picture_id_len == 1) {
data_ptr[0] = pic_id & 0x7F;
}
}
}
}

RTPPayloadVP8* RtpVP8Parser::parseVP8(unsigned char* data, int dataLength) {
// ELOG_DEBUG("Parsing VP8 %d bytes", dataLength);
RTPPayloadVP8* vp8 = new RTPPayloadVP8; // = &parsedPacket.info.VP8;
Expand Down
1 change: 1 addition & 0 deletions erizo/src/erizo/rtp/RtpVP8Parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ class RtpVP8Parser {
public:
RtpVP8Parser();
virtual ~RtpVP8Parser();
static void setVP8PictureID(unsigned char* data, int data_length, int picture_id);
erizo::RTPPayloadVP8* parseVP8(unsigned char* data, int datalength);
};
} // namespace erizo
Expand Down

0 comments on commit 1bb1dca

Please sign in to comment.