Bug 1272877 - dispatch GetAsSourceSurface() to main thread to prevent assert; r=jesup
MozReview-Commit-ID: 7Y5cuNFw8sm
--- a/dom/media/encoder/VP8TrackEncoder.cpp
+++ b/dom/media/encoder/VP8TrackEncoder.cpp
@@ -9,16 +9,17 @@
#include "libyuv.h"
#include "mozilla/gfx/2D.h"
#include "prsystem.h"
#include "VideoSegment.h"
#include "VideoUtils.h"
#include "vpx/vp8cx.h"
#include "vpx/vpx_encoder.h"
#include "WebMWriter.h"
+#include "mozilla/media/MediaUtils.h"
namespace mozilla {
LazyLogModule gVP8TrackEncoderLog("VP8TrackEncoder");
#define VP8LOG(msg, ...) MOZ_LOG(gVP8TrackEncoderLog, mozilla::LogLevel::Debug, \
(msg, ##__VA_ARGS__))
// Debug logging macro with object pointer and class name.
@@ -359,17 +360,17 @@ nsresult VP8TrackEncoder::PrepareRawFram
VP8LOG("Converting an %s frame to I420 failed\n", yuvFormat.c_str());
return NS_ERROR_FAILURE;
}
VP8LOG("Converted an %s frame to I420\n", yuvFormat.c_str());
} else {
// Not YCbCr at all. Try to get access to the raw data and convert.
- RefPtr<SourceSurface> surf = img->GetAsSourceSurface();
+ RefPtr<SourceSurface> surf = GetSourceSurface(img.forget());
if (!surf) {
VP8LOG("Getting surface from %s image failed\n", Stringify(format).c_str());
return NS_ERROR_FAILURE;
}
RefPtr<DataSourceSurface> data = surf->GetDataSurface();
if (!data) {
VP8LOG("Getting data surface from %s image with %s (%s) surface failed\n",
@@ -427,16 +428,47 @@ nsresult VP8TrackEncoder::PrepareRawFram
mVPXImageWrapper->planes[VPX_PLANE_V] = cr;
mVPXImageWrapper->stride[VPX_PLANE_Y] = mFrameWidth;
mVPXImageWrapper->stride[VPX_PLANE_U] = halfWidth;
mVPXImageWrapper->stride[VPX_PLANE_V] = halfWidth;
return NS_OK;
}
+void
+VP8TrackEncoder::ReplyGetSourceSurface(already_AddRefed<gfx::SourceSurface> aSurf)
+{
+ mSourceSurface = aSurf;
+}
+
+already_AddRefed<gfx::SourceSurface>
+VP8TrackEncoder::GetSourceSurface(already_AddRefed<Image> aImg)
+{
+ RefPtr<Image> img = aImg;
+ mSourceSurface = nullptr;
+ if (img) {
+ if (img->AsGLImage() && !NS_IsMainThread()) {
+ // GLImage::GetAsSourceSurface() only support main thread
+ RefPtr<Runnable> getsourcesurface_runnable =
+ media::NewRunnableFrom([this, img]() -> nsresult {
+ // Due to the parameter DISPATCH_SYNC, encoder thread will stock at
+ // MediaRecorder::Session::Extract(bool). There is no chance
+ // that TrackEncoder will be destroyed during this period. So
+ // there is no need to use RefPtr to hold TrackEncoder.
+ ReplyGetSourceSurface(img->GetAsSourceSurface());
+ return NS_OK;
+ });
+ NS_DispatchToMainThread(getsourcesurface_runnable, NS_DISPATCH_SYNC);
+ } else {
+ mSourceSurface = img->GetAsSourceSurface();
+ }
+ }
+ return mSourceSurface.forget();
+}
+
// These two define value used in GetNextEncodeOperation to determine the
// EncodeOperation for next target frame.
#define I_FRAME_RATIO (0.5)
#define SKIP_FRAME_RATIO (0.75)
/**
* Compares the elapsed time from the beginning of GetEncodedTrack and
* the processed frame duration in mSourceSegment
--- a/dom/media/encoder/VP8TrackEncoder.h
+++ b/dom/media/encoder/VP8TrackEncoder.h
@@ -31,16 +31,17 @@ class VP8TrackEncoder : public VideoTrac
public:
explicit VP8TrackEncoder(TrackRate aTrackRate);
virtual ~VP8TrackEncoder();
already_AddRefed<TrackMetadataBase> GetMetadata() final override;
nsresult GetEncodedTrack(EncodedFrameContainer& aData) final override;
+ void ReplyGetSourceSurface(already_AddRefed<gfx::SourceSurface> aSurf);
protected:
nsresult Init(int32_t aWidth, int32_t aHeight,
int32_t aDisplayWidth, int32_t aDisplayHeight) final override;
private:
// Calculate the target frame's encoded duration.
StreamTime CalculateEncodedDuration(StreamTime aDurationCopied);
@@ -55,16 +56,18 @@ private:
// Get the encoded data from encoder to aData.
// Return value: false if the vpx_codec_get_cx_data returns null
// for EOS detection.
bool GetEncodedPartitions(EncodedFrameContainer& aData);
// Prepare the input data to the mVPXImageWrapper for encoding.
nsresult PrepareRawFrame(VideoChunk &aChunk);
+ already_AddRefed<gfx::SourceSurface> GetSourceSurface(already_AddRefed<layers::Image> aImg);
+
// Output frame rate.
uint32_t mEncodedFrameRate;
// Duration for the output frame, reciprocal to mEncodedFrameRate.
StreamTime mEncodedFrameDuration;
// Encoded timestamp.
StreamTime mEncodedTimestamp;
// Duration to the next encode frame.
StreamTime mRemainingTicks;
@@ -83,13 +86,14 @@ private:
*/
VideoSegment mSourceSegment;
// VP8 relative members.
// Codec context structure.
nsAutoPtr<vpx_codec_ctx_t> mVPXContext;
// Image Descriptor.
nsAutoPtr<vpx_image_t> mVPXImageWrapper;
+ RefPtr<gfx::SourceSurface> mSourceSurface;
};
} // namespace mozilla
#endif