зеркало из https://github.com/mozilla/pjs.git
Bug 578536 - Ensure WebMReader properly tags its decoded samples with file offsets. r=doublec a=blocking2.0
This commit is contained in:
Родитель
a184b0edd8
Коммит
567824b841
|
@ -67,10 +67,10 @@ static const float NS_PER_S = 1e9;
|
|||
static const float MS_PER_S = 1e3;
|
||||
|
||||
NS_SPECIALIZE_TEMPLATE
|
||||
class nsAutoRefTraits<nestegg_packet> : public nsPointerRefTraits<nestegg_packet>
|
||||
class nsAutoRefTraits<NesteggPacketHolder> : public nsPointerRefTraits<NesteggPacketHolder>
|
||||
{
|
||||
public:
|
||||
static void Release(nestegg_packet* aPacket) { nestegg_free_packet(aPacket); }
|
||||
static void Release(NesteggPacketHolder* aHolder) { delete aHolder; }
|
||||
};
|
||||
|
||||
// Functions for reading and seeking using nsMediaStream required for
|
||||
|
@ -351,7 +351,7 @@ ogg_packet nsWebMReader::InitOggPacket(unsigned char* aData,
|
|||
return packet;
|
||||
}
|
||||
|
||||
PRBool nsWebMReader::DecodeAudioPacket(nestegg_packet* aPacket)
|
||||
PRBool nsWebMReader::DecodeAudioPacket(nestegg_packet* aPacket, PRInt64 aOffset)
|
||||
{
|
||||
mMonitor.AssertCurrentThreadIn();
|
||||
|
||||
|
@ -449,7 +449,7 @@ PRBool nsWebMReader::DecodeAudioPacket(nestegg_packet* aPacket)
|
|||
|
||||
PRInt64 time = tstamp_ms + total_duration;
|
||||
total_samples += samples;
|
||||
SoundData* s = new SoundData(0,
|
||||
SoundData* s = new SoundData(aOffset,
|
||||
time,
|
||||
duration,
|
||||
samples,
|
||||
|
@ -466,7 +466,7 @@ PRBool nsWebMReader::DecodeAudioPacket(nestegg_packet* aPacket)
|
|||
return PR_TRUE;
|
||||
}
|
||||
|
||||
nsReturnRef<nestegg_packet> nsWebMReader::NextPacket(TrackType aTrackType)
|
||||
nsReturnRef<NesteggPacketHolder> nsWebMReader::NextPacket(TrackType aTrackType)
|
||||
{
|
||||
// The packet queue that packets will be pushed on if they
|
||||
// are not the type we are interested in.
|
||||
|
@ -491,30 +491,31 @@ nsReturnRef<nestegg_packet> nsWebMReader::NextPacket(TrackType aTrackType)
|
|||
// Value of other track
|
||||
PRUint32 otherTrack = aTrackType == VIDEO ? mAudioTrack : mVideoTrack;
|
||||
|
||||
nsAutoRef<nestegg_packet> packet;
|
||||
nsAutoRef<NesteggPacketHolder> holder;
|
||||
|
||||
if (packets.GetSize() > 0) {
|
||||
packet.own(packets.PopFront());
|
||||
holder.own(packets.PopFront());
|
||||
} else {
|
||||
// Keep reading packets until we find a packet
|
||||
// for the track we want.
|
||||
do {
|
||||
nestegg_packet* p;
|
||||
int r = nestegg_read_packet(mContext, &p);
|
||||
nestegg_packet* packet;
|
||||
int r = nestegg_read_packet(mContext, &packet);
|
||||
if (r <= 0) {
|
||||
return nsReturnRef<nestegg_packet>();
|
||||
return nsReturnRef<NesteggPacketHolder>();
|
||||
}
|
||||
packet.own(p);
|
||||
PRInt64 offset = mDecoder->GetCurrentStream()->Tell();
|
||||
holder.own(new NesteggPacketHolder(packet, offset));
|
||||
|
||||
unsigned int track = 0;
|
||||
r = nestegg_packet_track(packet, &track);
|
||||
if (r == -1) {
|
||||
return nsReturnRef<nestegg_packet>();
|
||||
return nsReturnRef<NesteggPacketHolder>();
|
||||
}
|
||||
|
||||
if (hasOtherType && otherTrack == track) {
|
||||
// Save the packet for when we want these packets
|
||||
otherPackets.Push(packet.disown());
|
||||
otherPackets.Push(holder.disown());
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -525,7 +526,7 @@ nsReturnRef<nestegg_packet> nsWebMReader::NextPacket(TrackType aTrackType)
|
|||
} while (PR_TRUE);
|
||||
}
|
||||
|
||||
return packet.out();
|
||||
return holder.out();
|
||||
}
|
||||
|
||||
PRBool nsWebMReader::DecodeAudioData()
|
||||
|
@ -533,13 +534,13 @@ PRBool nsWebMReader::DecodeAudioData()
|
|||
MonitorAutoEnter mon(mMonitor);
|
||||
NS_ASSERTION(mDecoder->OnStateMachineThread() || mDecoder->OnDecodeThread(),
|
||||
"Should be on state machine thread or decode thread.");
|
||||
nsAutoRef<nestegg_packet> packet(NextPacket(AUDIO));
|
||||
if (!packet) {
|
||||
nsAutoRef<NesteggPacketHolder> holder(NextPacket(AUDIO));
|
||||
if (!holder) {
|
||||
mAudioQueue.Finish();
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
return DecodeAudioPacket(packet);
|
||||
return DecodeAudioPacket(holder->mPacket, holder->mOffset);
|
||||
}
|
||||
|
||||
PRBool nsWebMReader::DecodeVideoFrame(PRBool &aKeyframeSkip,
|
||||
|
@ -549,12 +550,13 @@ PRBool nsWebMReader::DecodeVideoFrame(PRBool &aKeyframeSkip,
|
|||
NS_ASSERTION(mDecoder->OnStateMachineThread() || mDecoder->OnDecodeThread(),
|
||||
"Should be on state machine or decode thread.");
|
||||
|
||||
nsAutoRef<nestegg_packet> packet(NextPacket(VIDEO));
|
||||
if (!packet) {
|
||||
nsAutoRef<NesteggPacketHolder> holder(NextPacket(VIDEO));
|
||||
if (!holder) {
|
||||
mVideoQueue.Finish();
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
nestegg_packet* packet = holder->mPacket;
|
||||
unsigned int track = 0;
|
||||
int r = nestegg_packet_track(packet, &track);
|
||||
if (r == -1) {
|
||||
|
@ -579,13 +581,13 @@ PRBool nsWebMReader::DecodeVideoFrame(PRBool &aKeyframeSkip,
|
|||
// video frame.
|
||||
uint64_t next_tstamp = 0;
|
||||
{
|
||||
nsAutoRef<nestegg_packet> next_packet(NextPacket(VIDEO));
|
||||
if (next_packet) {
|
||||
r = nestegg_packet_tstamp(next_packet, &next_tstamp);
|
||||
nsAutoRef<NesteggPacketHolder> next_holder(NextPacket(VIDEO));
|
||||
if (next_holder) {
|
||||
r = nestegg_packet_tstamp(next_holder->mPacket, &next_tstamp);
|
||||
if (r == -1) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
mVideoPackets.PushFront(next_packet.disown());
|
||||
mVideoPackets.PushFront(next_holder.disown());
|
||||
} else {
|
||||
MonitorAutoExit exitMon(mMonitor);
|
||||
MonitorAutoEnter decoderMon(mDecoder->GetMonitor());
|
||||
|
@ -661,7 +663,7 @@ PRBool nsWebMReader::DecodeVideoFrame(PRBool &aKeyframeSkip,
|
|||
|
||||
VideoData *v = VideoData::Create(mInfo,
|
||||
mDecoder->GetImageContainer(),
|
||||
-1,
|
||||
holder->mOffset,
|
||||
tstamp_ms,
|
||||
next_tstamp / NS_PER_MS,
|
||||
b,
|
||||
|
|
|
@ -54,10 +54,35 @@
|
|||
|
||||
class nsMediaDecoder;
|
||||
|
||||
// Holds a nestegg_packet, and its file offset. This is needed so we
|
||||
// know the offset in the file we've played up to, in order to calculate
|
||||
// whether it's likely we can play through to the end without needing
|
||||
// to stop to buffer, given the current download rate.
|
||||
class NesteggPacketHolder {
|
||||
public:
|
||||
NesteggPacketHolder(nestegg_packet* aPacket, PRInt64 aOffset)
|
||||
: mPacket(aPacket), mOffset(aOffset)
|
||||
{
|
||||
MOZ_COUNT_CTOR(NesteggPacketHolder);
|
||||
}
|
||||
~NesteggPacketHolder() {
|
||||
MOZ_COUNT_DTOR(NesteggPacketHolder);
|
||||
nestegg_free_packet(mPacket);
|
||||
}
|
||||
nestegg_packet* mPacket;
|
||||
// Offset in bytes. This is the offset of the end of the Block
|
||||
// which contains the packet.
|
||||
PRInt64 mOffset;
|
||||
private:
|
||||
// Copy constructor and assignment operator not implemented. Don't use them!
|
||||
NesteggPacketHolder(const NesteggPacketHolder &aOther);
|
||||
NesteggPacketHolder& operator= (NesteggPacketHolder const& aOther);
|
||||
};
|
||||
|
||||
// Thread and type safe wrapper around nsDeque.
|
||||
class PacketQueueDeallocator : public nsDequeFunctor {
|
||||
virtual void* operator() (void* anObject) {
|
||||
nestegg_free_packet(static_cast<nestegg_packet*>(anObject));
|
||||
delete static_cast<NesteggPacketHolder*>(anObject);
|
||||
return nsnull;
|
||||
}
|
||||
};
|
||||
|
@ -79,23 +104,23 @@ class PacketQueue : private nsDeque {
|
|||
return nsDeque::GetSize();
|
||||
}
|
||||
|
||||
inline void Push(nestegg_packet* aItem) {
|
||||
inline void Push(NesteggPacketHolder* aItem) {
|
||||
NS_ASSERTION(aItem, "NULL pushed to PacketQueue");
|
||||
nsDeque::Push(aItem);
|
||||
}
|
||||
|
||||
inline void PushFront(nestegg_packet* aItem) {
|
||||
inline void PushFront(NesteggPacketHolder* aItem) {
|
||||
NS_ASSERTION(aItem, "NULL pushed to PacketQueue");
|
||||
nsDeque::PushFront(aItem);
|
||||
}
|
||||
|
||||
inline nestegg_packet* PopFront() {
|
||||
return static_cast<nestegg_packet*>(nsDeque::PopFront());
|
||||
inline NesteggPacketHolder* PopFront() {
|
||||
return static_cast<NesteggPacketHolder*>(nsDeque::PopFront());
|
||||
}
|
||||
|
||||
void Reset() {
|
||||
while (GetSize() > 0) {
|
||||
nestegg_free_packet(PopFront());
|
||||
delete PopFront();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -144,7 +169,7 @@ private:
|
|||
// Read a packet from the nestegg file. Returns NULL if all packets for
|
||||
// the particular track have been read. Pass VIDEO or AUDIO to indicate the
|
||||
// type of the packet we want to read.
|
||||
nsReturnRef<nestegg_packet> NextPacket(TrackType aTrackType);
|
||||
nsReturnRef<NesteggPacketHolder> NextPacket(TrackType aTrackType);
|
||||
|
||||
// Returns an initialized ogg packet with data obtained from the WebM container.
|
||||
ogg_packet InitOggPacket(unsigned char* aData,
|
||||
|
@ -159,7 +184,7 @@ private:
|
|||
// or an un-recoverable read error has occured. The reader's monitor
|
||||
// must be held during this call. This function will free the packet
|
||||
// so the caller must not use the packet after calling.
|
||||
PRBool DecodeAudioPacket(nestegg_packet* aPacket);
|
||||
PRBool DecodeAudioPacket(nestegg_packet* aPacket, PRInt64 aOffset);
|
||||
|
||||
// Release context and set to null. Called when an error occurs during
|
||||
// reading metadata or destruction of the reader itself.
|
||||
|
|
Загрузка…
Ссылка в новой задаче