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/decoding_state.h"
|
||||||
|
|
||||||
#include "modules/video_coding/main/source/frame_buffer.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/jitter_buffer_common.h"
|
||||||
#include "modules/video_coding/main/source/packet.h"
|
#include "modules/video_coding/main/source/packet.h"
|
||||||
|
|
||||||
#include "modules/interface/module_common_types.h"
|
#include "modules/interface/module_common_types.h"
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
@ -162,21 +162,20 @@ bool VCMDecodingState::ContinuousPictureId(int picture_id) const {
|
|||||||
// First, check if applicable.
|
// First, check if applicable.
|
||||||
if (picture_id == kNoPictureId || picture_id_ == kNoPictureId)
|
if (picture_id == kNoPictureId || picture_id_ == kNoPictureId)
|
||||||
return false;
|
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
|
// Wrap
|
||||||
if (local_pic_id >= (1 << 8)) {
|
if (picture_id_ >= 0x80) {
|
||||||
// 15 bits used for picture id
|
// 15 bits used for picture id
|
||||||
return (((local_pic_id + 1) % 0x7FFF) == new_pic_id);
|
return ((next_picture_id & 0x7FFF) == picture_id);
|
||||||
} else {
|
} else {
|
||||||
// 7 bits used for picture id
|
// 7 bits used for picture id
|
||||||
return (((local_pic_id + 1) % 0x7F) == new_pic_id);
|
return ((next_picture_id & 0x7F) == picture_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// No wrap
|
// No wrap
|
||||||
return (local_pic_id + 1 == new_pic_id);
|
return (next_picture_id == picture_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VCMDecodingState::ContinuousSeqNum(uint16_t seq_num) const {
|
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.
|
// Current implementation: Look for base layer continuity.
|
||||||
if (temporal_id != 0)
|
if (temporal_id != 0)
|
||||||
return false;
|
return false;
|
||||||
return (static_cast<uint8_t>(tl0_pic_id_ + 1) ==
|
return (static_cast<uint8_t>(tl0_pic_id_ + 1) == tl0_pic_id);
|
||||||
static_cast<uint8_t>(tl0_pic_id));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
@ -1720,8 +1720,7 @@ VCMJitterBuffer::RecycleFramesUntilKeyFrame()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Remove up to oldest key frame
|
// Remove up to oldest key frame
|
||||||
bool foundKeyFrame = false;
|
while (oldestFrameListItem != NULL)
|
||||||
while (oldestFrameListItem != NULL && !foundKeyFrame)
|
|
||||||
{
|
{
|
||||||
// Throw at least one frame.
|
// Throw at least one frame.
|
||||||
_dropCount++;
|
_dropCount++;
|
||||||
@ -1737,21 +1736,15 @@ VCMJitterBuffer::RecycleFramesUntilKeyFrame()
|
|||||||
{
|
{
|
||||||
oldestFrame = oldestFrameListItem->GetItem();
|
oldestFrame = oldestFrameListItem->GetItem();
|
||||||
}
|
}
|
||||||
|
if (oldestFrame != NULL && oldestFrame->FrameType() == kVideoFrameKey)
|
||||||
if (oldestFrame != NULL)
|
|
||||||
{
|
|
||||||
foundKeyFrame = foundKeyFrame ||
|
|
||||||
(oldestFrame->FrameType() != kVideoFrameDelta);
|
|
||||||
if (foundKeyFrame)
|
|
||||||
{
|
{
|
||||||
// Fake the lastDecodedState to match this key frame.
|
// Fake the lastDecodedState to match this key frame.
|
||||||
_lastDecodedState.SetStateOneBack(oldestFrame);
|
_lastDecodedState.SetStateOneBack(oldestFrame);
|
||||||
break;
|
return true;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_lastDecodedState.Reset(); // TODO (mikhal): no sync
|
_lastDecodedState.Reset(); // TODO (mikhal): no sync
|
||||||
return foundKeyFrame;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Must be called under the critical section _critSect.
|
// Must be called under the critical section _critSect.
|
||||||
|
@ -2428,6 +2428,53 @@ int JitterBufferTest(CmdArgs& args)
|
|||||||
|
|
||||||
jb.Flush();
|
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();
|
jb.Stop();
|
||||||
|
|
||||||
printf("DONE !!!\n");
|
printf("DONE !!!\n");
|
||||||
|
Loading…
Reference in New Issue
Block a user