Only reset the last decoded sequence number after flushing until key frame.
We can't reset the complete last decoded state when we recycle until a key frame because that will allow any delta frame to be decoded afterwards, and since the decoder isn't reset we will get decode errors. BUG= TEST= Review URL: http://webrtc-codereview.appspot.com/330003 git-svn-id: http://webrtc.googlecode.com/svn/trunk@1295 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
parent
1ce66e4dfb
commit
39670f6aa6
@ -9,10 +9,10 @@
|
||||
*/
|
||||
|
||||
#include "modules/video_coding/main/source/decoding_state.h"
|
||||
|
||||
#include "modules/video_coding/main/source/frame_buffer.h"
|
||||
#include "modules/video_coding/main/source/jitter_buffer_common.h"
|
||||
#include "modules/video_coding/main/source/packet.h"
|
||||
|
||||
#include "modules/interface/module_common_types.h"
|
||||
|
||||
namespace webrtc {
|
||||
@ -76,7 +76,7 @@ void VCMDecodingState::SetState(const VCMFrameBuffer* frame) {
|
||||
|
||||
void VCMDecodingState::SetStateOneBack(const VCMFrameBuffer* frame) {
|
||||
assert(frame != NULL && frame->GetHighSeqNum() >= 0);
|
||||
sequence_num_ = static_cast <uint16_t>(frame->GetHighSeqNum()) - 1u;
|
||||
sequence_num_ = static_cast<uint16_t>(frame->GetHighSeqNum()) - 1u;
|
||||
time_stamp_ = frame->TimeStamp() - 1u;
|
||||
temporal_id_ = frame->TemporalId();
|
||||
if (frame->PictureId() != kNoPictureId) {
|
||||
@ -162,21 +162,20 @@ bool VCMDecodingState::ContinuousPictureId(int picture_id) const {
|
||||
// First, check if applicable.
|
||||
if (picture_id == kNoPictureId || picture_id_ == kNoPictureId)
|
||||
return false;
|
||||
uint16_t local_pic_id = static_cast<uint16_t>(picture_id_);
|
||||
uint16_t new_pic_id = static_cast<uint16_t>(picture_id);
|
||||
|
||||
if (new_pic_id < local_pic_id) {
|
||||
int next_picture_id = picture_id_ + 1;
|
||||
if (picture_id < picture_id_) {
|
||||
// Wrap
|
||||
if (local_pic_id >= (1 << 8)) {
|
||||
if (picture_id_ >= 0x80) {
|
||||
// 15 bits used for picture id
|
||||
return (((local_pic_id + 1) % 0x7FFF) == new_pic_id);
|
||||
return ((next_picture_id & 0x7FFF) == picture_id);
|
||||
} else {
|
||||
// 7 bits used for picture id
|
||||
return (((local_pic_id + 1) % 0x7F) == new_pic_id);
|
||||
return ((next_picture_id & 0x7F) == picture_id);
|
||||
}
|
||||
}
|
||||
// No wrap
|
||||
return (local_pic_id + 1 == new_pic_id);
|
||||
return (next_picture_id == picture_id);
|
||||
}
|
||||
|
||||
bool VCMDecodingState::ContinuousSeqNum(uint16_t seq_num) const {
|
||||
@ -197,8 +196,7 @@ bool VCMDecodingState::ContinuousLayer(int temporal_id,
|
||||
// Current implementation: Look for base layer continuity.
|
||||
if (temporal_id != 0)
|
||||
return false;
|
||||
return (static_cast<uint8_t>(tl0_pic_id_ + 1) ==
|
||||
static_cast<uint8_t>(tl0_pic_id));
|
||||
return (static_cast<uint8_t>(tl0_pic_id_ + 1) == tl0_pic_id);
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
|
@ -1720,8 +1720,7 @@ VCMJitterBuffer::RecycleFramesUntilKeyFrame()
|
||||
}
|
||||
|
||||
// Remove up to oldest key frame
|
||||
bool foundKeyFrame = false;
|
||||
while (oldestFrameListItem != NULL && !foundKeyFrame)
|
||||
while (oldestFrameListItem != NULL)
|
||||
{
|
||||
// Throw at least one frame.
|
||||
_dropCount++;
|
||||
@ -1737,21 +1736,15 @@ VCMJitterBuffer::RecycleFramesUntilKeyFrame()
|
||||
{
|
||||
oldestFrame = oldestFrameListItem->GetItem();
|
||||
}
|
||||
|
||||
if (oldestFrame != NULL)
|
||||
if (oldestFrame != NULL && oldestFrame->FrameType() == kVideoFrameKey)
|
||||
{
|
||||
foundKeyFrame = foundKeyFrame ||
|
||||
(oldestFrame->FrameType() != kVideoFrameDelta);
|
||||
if (foundKeyFrame)
|
||||
{
|
||||
// Fake the lastDecodedState to match this key frame.
|
||||
_lastDecodedState.SetStateOneBack(oldestFrame);
|
||||
break;
|
||||
}
|
||||
// Fake the lastDecodedState to match this key frame.
|
||||
_lastDecodedState.SetStateOneBack(oldestFrame);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
_lastDecodedState.Reset(); // TODO (mikhal): no sync
|
||||
return foundKeyFrame;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Must be called under the critical section _critSect.
|
||||
|
@ -2428,6 +2428,53 @@ int JitterBufferTest(CmdArgs& args)
|
||||
|
||||
jb.Flush();
|
||||
|
||||
// Verify that a key frame is the next frame after the nack list gets full.
|
||||
jb.SetNackMode(kNackInfinite, -1, -1);
|
||||
seqNum += 1;
|
||||
timeStamp += 33 * 90;
|
||||
packet.seqNum = seqNum;
|
||||
packet.timestamp = timeStamp;
|
||||
packet.frameType = kVideoFrameKey;
|
||||
packet.isFirstPacket = true;
|
||||
packet.completeNALU = kNaluComplete;
|
||||
packet.markerBit = true;
|
||||
TEST(frameIn = jb.GetFrame(packet));
|
||||
TEST(kFirstPacket == jb.InsertPacket(frameIn, packet));
|
||||
|
||||
TEST(jb.GetCompleteFrameForDecoding(0) != NULL);
|
||||
|
||||
seqNum += kNackHistoryLength + 1;
|
||||
timeStamp += 33 * 90;
|
||||
packet.seqNum = seqNum;
|
||||
packet.timestamp = timeStamp;
|
||||
packet.frameType = kVideoFrameDelta;
|
||||
packet.isFirstPacket = true;
|
||||
packet.completeNALU = kNaluComplete;
|
||||
packet.markerBit = true;
|
||||
TEST(frameIn = jb.GetFrame(packet));
|
||||
TEST(kFirstPacket == jb.InsertPacket(frameIn, packet));
|
||||
|
||||
TEST(jb.GetCompleteFrameForDecoding(0) == NULL);
|
||||
|
||||
uint16_t nack_list_length = kNackHistoryLength;
|
||||
uint16_t *nack_list;
|
||||
nack_list = jb.GetNackList(nack_list_length, extended);
|
||||
TEST(nack_list_length == 0xffff && nack_list == NULL);
|
||||
|
||||
seqNum += 1;
|
||||
timeStamp += 33 * 90;
|
||||
packet.seqNum = seqNum;
|
||||
packet.timestamp = timeStamp;
|
||||
packet.frameType = kVideoFrameDelta;
|
||||
packet.isFirstPacket = true;
|
||||
packet.completeNALU = kNaluComplete;
|
||||
packet.markerBit = true;
|
||||
TEST(frameIn = jb.GetFrame(packet));
|
||||
TEST(kFirstPacket == jb.InsertPacket(frameIn, packet));
|
||||
|
||||
TEST(jb.GetCompleteFrameForDecoding(0) == NULL);
|
||||
TEST(jb.GetFrameForDecoding() == NULL);
|
||||
|
||||
jb.Stop();
|
||||
|
||||
printf("DONE !!!\n");
|
||||
|
Loading…
Reference in New Issue
Block a user