Bug 1157840 - Refcount NesteggPacketHolder. r=kinetik

This commit is contained in:
Bobby Holley 2015-04-23 11:39:32 -07:00
parent f54e89bb60
commit 4cf40b7bd9
4 changed files with 49 additions and 73 deletions

View File

@ -156,7 +156,7 @@ IntelWebMVideoDecoder::Init(unsigned int aWidth, unsigned int aHeight)
bool bool
IntelWebMVideoDecoder::Demux(nsRefPtr<VP8Sample>& aSample, bool* aEOS) IntelWebMVideoDecoder::Demux(nsRefPtr<VP8Sample>& aSample, bool* aEOS)
{ {
nsAutoRef<NesteggPacketHolder> holder(mReader->NextPacket(WebMReader::VIDEO)); nsRefPtr<NesteggPacketHolder> holder(mReader->NextPacket(WebMReader::VIDEO));
if (!holder) { if (!holder) {
return false; return false;
} }
@ -185,13 +185,13 @@ IntelWebMVideoDecoder::Demux(nsRefPtr<VP8Sample>& aSample, bool* aEOS)
// end of the resource, use the file's duration as the end time of this // end of the resource, use the file's duration as the end time of this
// video frame. // video frame.
uint64_t next_tstamp = 0; uint64_t next_tstamp = 0;
nsAutoRef<NesteggPacketHolder> next_holder(mReader->NextPacket(WebMReader::VIDEO)); nsRefPtr<NesteggPacketHolder> next_holder(mReader->NextPacket(WebMReader::VIDEO));
if (next_holder) { if (next_holder) {
r = nestegg_packet_tstamp(next_holder->mPacket, &next_tstamp); r = nestegg_packet_tstamp(next_holder->mPacket, &next_tstamp);
if (r == -1) { if (r == -1) {
return false; return false;
} }
mReader->PushVideoPacket(next_holder.disown()); mReader->PushVideoPacket(next_holder.forget());
} else { } else {
next_tstamp = tstamp; next_tstamp = tstamp;
next_tstamp += tstamp - mReader->GetLastVideoFrameTime(); next_tstamp += tstamp - mReader->GetLastVideoFrameTime();

View File

@ -80,7 +80,7 @@ SoftwareWebMVideoDecoder::DecodeVideoFrame(bool &aKeyframeSkip,
// stats counters using the AutoNotifyDecoded stack-based class. // stats counters using the AutoNotifyDecoded stack-based class.
AbstractMediaDecoder::AutoNotifyDecoded a(mReader->GetDecoder()); AbstractMediaDecoder::AutoNotifyDecoded a(mReader->GetDecoder());
nsAutoRef<NesteggPacketHolder> holder(mReader->NextPacket(WebMReader::VIDEO)); nsRefPtr<NesteggPacketHolder> holder(mReader->NextPacket(WebMReader::VIDEO));
if (!holder) { if (!holder) {
return false; return false;
} }
@ -109,13 +109,13 @@ SoftwareWebMVideoDecoder::DecodeVideoFrame(bool &aKeyframeSkip,
// end of the resource, use the file's duration as the end time of this // end of the resource, use the file's duration as the end time of this
// video frame. // video frame.
uint64_t next_tstamp = 0; uint64_t next_tstamp = 0;
nsAutoRef<NesteggPacketHolder> next_holder(mReader->NextPacket(WebMReader::VIDEO)); nsRefPtr<NesteggPacketHolder> next_holder(mReader->NextPacket(WebMReader::VIDEO));
if (next_holder) { if (next_holder) {
r = nestegg_packet_tstamp(next_holder->mPacket, &next_tstamp); r = nestegg_packet_tstamp(next_holder->mPacket, &next_tstamp);
if (r == -1) { if (r == -1) {
return false; return false;
} }
mReader->PushVideoPacket(next_holder.disown()); mReader->PushVideoPacket(next_holder.forget());
} else { } else {
next_tstamp = tstamp; next_tstamp = tstamp;
next_tstamp += tstamp - mReader->GetLastVideoFrameTime(); next_tstamp += tstamp - mReader->GetLastVideoFrameTime();

View File

@ -867,7 +867,7 @@ bool WebMReader::DecodeOpus(const unsigned char* aData, size_t aLength,
return true; return true;
} }
nsReturnRef<NesteggPacketHolder> WebMReader::NextPacket(TrackType aTrackType) already_AddRefed<NesteggPacketHolder> WebMReader::NextPacket(TrackType aTrackType)
{ {
// The packet queue that packets will be pushed on if they // The packet queue that packets will be pushed on if they
// are not the type we are interested in. // are not the type we are interested in.
@ -892,10 +892,10 @@ nsReturnRef<NesteggPacketHolder> WebMReader::NextPacket(TrackType aTrackType)
// Value of other track // Value of other track
uint32_t otherTrack = aTrackType == VIDEO ? mAudioTrack : mVideoTrack; uint32_t otherTrack = aTrackType == VIDEO ? mAudioTrack : mVideoTrack;
nsAutoRef<NesteggPacketHolder> holder; nsRefPtr<NesteggPacketHolder> holder;
if (packets.GetSize() > 0) { if (packets.GetSize() > 0) {
holder.own(packets.PopFront()); holder = packets.PopFront();
} else { } else {
// Keep reading packets until we find a packet // Keep reading packets until we find a packet
// for the track we want. // for the track we want.
@ -903,20 +903,20 @@ nsReturnRef<NesteggPacketHolder> WebMReader::NextPacket(TrackType aTrackType)
nestegg_packet* packet; nestegg_packet* packet;
int r = nestegg_read_packet(mContext, &packet); int r = nestegg_read_packet(mContext, &packet);
if (r <= 0) { if (r <= 0) {
return nsReturnRef<NesteggPacketHolder>(); return nullptr;
} }
int64_t offset = mDecoder->GetResource()->Tell(); int64_t offset = mDecoder->GetResource()->Tell();
holder.own(new NesteggPacketHolder(packet, offset)); holder = new NesteggPacketHolder(packet, offset);
unsigned int track = 0; unsigned int track = 0;
r = nestegg_packet_track(packet, &track); r = nestegg_packet_track(packet, &track);
if (r == -1) { if (r == -1) {
return nsReturnRef<NesteggPacketHolder>(); return nullptr;
} }
if (hasOtherType && otherTrack == track) { if (hasOtherType && otherTrack == track) {
// Save the packet for when we want these packets // Save the packet for when we want these packets
otherPackets.Push(holder.disown()); otherPackets.Push(holder.forget());
continue; continue;
} }
@ -927,14 +927,14 @@ nsReturnRef<NesteggPacketHolder> WebMReader::NextPacket(TrackType aTrackType)
} while (true); } while (true);
} }
return holder.out(); return holder.forget();
} }
bool WebMReader::DecodeAudioData() bool WebMReader::DecodeAudioData()
{ {
MOZ_ASSERT(OnTaskQueue()); MOZ_ASSERT(OnTaskQueue());
nsAutoRef<NesteggPacketHolder> holder(NextPacket(AUDIO)); nsRefPtr<NesteggPacketHolder> holder(NextPacket(AUDIO));
if (!holder) { if (!holder) {
return false; return false;
} }
@ -947,7 +947,7 @@ bool WebMReader::FilterPacketByTime(int64_t aEndTime, WebMPacketQueue& aOutput)
// Push the video frames to the aOutput which's timestamp is less // Push the video frames to the aOutput which's timestamp is less
// than aEndTime. // than aEndTime.
while (true) { while (true) {
nsAutoRef<NesteggPacketHolder> holder(NextPacket(VIDEO)); nsRefPtr<NesteggPacketHolder> holder(NextPacket(VIDEO));
if (!holder) { if (!holder) {
break; break;
} }
@ -958,10 +958,10 @@ bool WebMReader::FilterPacketByTime(int64_t aEndTime, WebMPacketQueue& aOutput)
} }
uint64_t tstamp_usecs = tstamp / NS_PER_USEC; uint64_t tstamp_usecs = tstamp / NS_PER_USEC;
if (tstamp_usecs >= (uint64_t)aEndTime) { if (tstamp_usecs >= (uint64_t)aEndTime) {
PushVideoPacket(holder.disown()); PushVideoPacket(holder.forget());
return true; return true;
} else { } else {
aOutput.PushFront(holder.disown()); aOutput.PushFront(holder.forget());
} }
} }
@ -984,7 +984,7 @@ int64_t WebMReader::GetNextKeyframeTime(int64_t aTimeThreshold)
bool foundKeyframe = false; bool foundKeyframe = false;
int64_t keyframeTime = -1; int64_t keyframeTime = -1;
while (!foundKeyframe) { while (!foundKeyframe) {
nsAutoRef<NesteggPacketHolder> holder(NextPacket(VIDEO)); nsRefPtr<NesteggPacketHolder> holder(NextPacket(VIDEO));
if (!holder) { if (!holder) {
break; break;
} }
@ -1022,7 +1022,7 @@ int64_t WebMReader::GetNextKeyframeTime(int64_t aTimeThreshold)
break; break;
} }
} }
skipPacketQueue.PushFront(holder.disown()); skipPacketQueue.PushFront(holder.forget());
} }
uint32_t size = skipPacketQueue.GetSize(); uint32_t size = skipPacketQueue.GetSize();
@ -1047,9 +1047,9 @@ bool WebMReader::DecodeVideoFrame(bool &aKeyframeSkip, int64_t aTimeThreshold)
return mVideoDecoder->DecodeVideoFrame(aKeyframeSkip, aTimeThreshold); return mVideoDecoder->DecodeVideoFrame(aKeyframeSkip, aTimeThreshold);
} }
void WebMReader::PushVideoPacket(NesteggPacketHolder* aItem) void WebMReader::PushVideoPacket(already_AddRefed<NesteggPacketHolder> aItem)
{ {
mVideoPackets.PushFront(aItem); mVideoPackets.PushFront(Move(aItem));
} }
nsRefPtr<MediaDecoderReader::SeekPromise> nsRefPtr<MediaDecoderReader::SeekPromise>

View File

@ -8,7 +8,6 @@
#include <stdint.h> #include <stdint.h>
#include "nsDeque.h"
#include "MediaDecoderReader.h" #include "MediaDecoderReader.h"
#include "nsAutoRef.h" #include "nsAutoRef.h"
#include "nestegg/nestegg.h" #include "nestegg/nestegg.h"
@ -32,81 +31,58 @@
// to stop to buffer, given the current download rate. // to stop to buffer, given the current download rate.
class NesteggPacketHolder { class NesteggPacketHolder {
public: public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(NesteggPacketHolder)
NesteggPacketHolder(nestegg_packet* aPacket, int64_t aOffset) NesteggPacketHolder(nestegg_packet* aPacket, int64_t aOffset)
: mPacket(aPacket), mOffset(aOffset) : mPacket(aPacket), mOffset(aOffset) {}
{
MOZ_COUNT_CTOR(NesteggPacketHolder);
}
~NesteggPacketHolder() {
MOZ_COUNT_DTOR(NesteggPacketHolder);
nestegg_free_packet(mPacket);
}
nestegg_packet* mPacket; nestegg_packet* mPacket;
// Offset in bytes. This is the offset of the end of the Block // Offset in bytes. This is the offset of the end of the Block
// which contains the packet. // which contains the packet.
int64_t mOffset; int64_t mOffset;
private: private:
~NesteggPacketHolder() {
nestegg_free_packet(mPacket);
}
// Copy constructor and assignment operator not implemented. Don't use them! // Copy constructor and assignment operator not implemented. Don't use them!
NesteggPacketHolder(const NesteggPacketHolder &aOther); NesteggPacketHolder(const NesteggPacketHolder &aOther);
NesteggPacketHolder& operator= (NesteggPacketHolder const& aOther); NesteggPacketHolder& operator= (NesteggPacketHolder const& aOther);
}; };
template <>
class nsAutoRefTraits<NesteggPacketHolder> : public nsPointerRefTraits<NesteggPacketHolder>
{
public:
static void Release(NesteggPacketHolder* aHolder) { delete aHolder; }
};
namespace mozilla { namespace mozilla {
class WebMBufferedState; class WebMBufferedState;
static const unsigned NS_PER_USEC = 1000; static const unsigned NS_PER_USEC = 1000;
static const double NS_PER_S = 1e9; static const double NS_PER_S = 1e9;
// Thread and type safe wrapper around nsDeque. // Queue for holding nestegg packets.
class PacketQueueDeallocator : public nsDequeFunctor { class WebMPacketQueue {
virtual void* operator() (void* aObject) {
delete static_cast<NesteggPacketHolder*>(aObject);
return nullptr;
}
};
// Typesafe queue for holding nestegg packets. It has
// ownership of the items in the queue and will free them
// when destroyed.
class WebMPacketQueue : private nsDeque {
public: public:
WebMPacketQueue() int32_t GetSize() {
: nsDeque(new PacketQueueDeallocator()) return mQueue.size();
{}
~WebMPacketQueue() {
Reset();
} }
inline int32_t GetSize() { void Push(already_AddRefed<NesteggPacketHolder> aItem) {
return nsDeque::GetSize(); mQueue.push_back(Move(aItem));
} }
inline void Push(NesteggPacketHolder* aItem) { void PushFront(already_AddRefed<NesteggPacketHolder> aItem) {
NS_ASSERTION(aItem, "NULL pushed to WebMPacketQueue"); mQueue.push_front(Move(aItem));
nsDeque::Push(aItem);
} }
inline void PushFront(NesteggPacketHolder* aItem) { already_AddRefed<NesteggPacketHolder> PopFront() {
NS_ASSERTION(aItem, "NULL pushed to WebMPacketQueue"); nsRefPtr<NesteggPacketHolder> result = mQueue.front().forget();
nsDeque::PushFront(aItem); mQueue.pop_front();
} return result.forget();
inline NesteggPacketHolder* PopFront() {
return static_cast<NesteggPacketHolder*>(nsDeque::PopFront());
} }
void Reset() { void Reset() {
while (GetSize() > 0) { while (!mQueue.empty()) {
delete PopFront(); mQueue.pop_front();
} }
} }
private:
std::deque<nsRefPtr<NesteggPacketHolder>> mQueue;
}; };
class WebMReader; class WebMReader;
@ -175,10 +151,10 @@ public:
// Read a packet from the nestegg file. Returns nullptr if all packets for // Read a packet from the nestegg file. Returns nullptr if all packets for
// the particular track have been read. Pass VIDEO or AUDIO to indicate the // the particular track have been read. Pass VIDEO or AUDIO to indicate the
// type of the packet we want to read. // type of the packet we want to read.
nsReturnRef<NesteggPacketHolder> NextPacket(TrackType aTrackType); already_AddRefed<NesteggPacketHolder> NextPacket(TrackType aTrackType);
// Pushes a packet to the front of the video packet queue. // Pushes a packet to the front of the video packet queue.
virtual void PushVideoPacket(NesteggPacketHolder* aItem); virtual void PushVideoPacket(already_AddRefed<NesteggPacketHolder> aItem);
int GetVideoCodec(); int GetVideoCodec();
nsIntRect GetPicture(); nsIntRect GetPicture();
@ -245,7 +221,7 @@ private:
uint64_t mSeekPreroll; // Nanoseconds to discard after seeking. uint64_t mSeekPreroll; // Nanoseconds to discard after seeking.
// Queue of video and audio packets that have been read but not decoded. These // Queue of video and audio packets that have been read but not decoded. These
// must only be accessed from the state machine thread. // must only be accessed from the decode thread.
WebMPacketQueue mVideoPackets; WebMPacketQueue mVideoPackets;
WebMPacketQueue mAudioPackets; WebMPacketQueue mAudioPackets;