[SkVideoEncoder] Allow clients to control the color type
Change-Id: If57514c9e7e8d0a417eb9388873bbb348fc49076 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/247384 Commit-Queue: Mike Klein <mtklein@google.com> Reviewed-by: Mike Klein <mtklein@google.com>
This commit is contained in:
parent
232e3301c7
commit
10e5257ec9
@ -231,10 +231,9 @@ bool SkVideoEncoder::beginRecording(SkISize dim, int fps) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// need opaque and bgra to efficiently use libyuv / convert-to-yuv-420
|
||||
SkAlphaType alphaType = kOpaque_SkAlphaType;
|
||||
sk_sp<SkColorSpace> cs = nullptr; // should we use this?
|
||||
fInfo = SkImageInfo::Make(dim, kRGBA_8888_SkColorType, alphaType, cs);
|
||||
fInfo = SkImageInfo::MakeN32(dim.width(), dim.height(), alphaType, cs);
|
||||
if (!this->init(fps)) {
|
||||
return false;
|
||||
}
|
||||
@ -242,14 +241,15 @@ bool SkVideoEncoder::beginRecording(SkISize dim, int fps) {
|
||||
fCurrentPTS = 0;
|
||||
fDeltaPTS = 1;
|
||||
|
||||
SkASSERT(sws_isSupportedInput(AV_PIX_FMT_RGBA) > 0);
|
||||
const auto fmt = kN32_SkColorType == kRGBA_8888_SkColorType ? AV_PIX_FMT_RGBA : AV_PIX_FMT_BGRA;
|
||||
SkASSERT(sws_isSupportedInput(fmt) > 0);
|
||||
SkASSERT(sws_isSupportedOutput(AV_PIX_FMT_YUV420P) > 0);
|
||||
// sws_getCachedContext takes in either null or a previous ctx. It returns either a new ctx,
|
||||
// or the same as the input if it is compatible with the inputs. Thus we never have to
|
||||
// explicitly release our ctx until the destructor, since sws_getCachedContext takes care
|
||||
// of freeing the old as needed if/when it returns a new one.
|
||||
fSWScaleCtx = sws_getCachedContext(fSWScaleCtx,
|
||||
dim.width(), dim.height(), AV_PIX_FMT_RGBA,
|
||||
dim.width(), dim.height(), fmt,
|
||||
dim.width(), dim.height(), AV_PIX_FMT_YUV420P,
|
||||
SWS_FAST_BILINEAR, nullptr, nullptr, nullptr);
|
||||
return fSWScaleCtx != nullptr;
|
||||
@ -259,6 +259,9 @@ bool SkVideoEncoder::addFrame(const SkPixmap& pm) {
|
||||
if (!is_valid(pm.dimensions())) {
|
||||
return false;
|
||||
}
|
||||
if (pm.info().colorType() != fInfo.colorType()) {
|
||||
return false;
|
||||
}
|
||||
/* make sure the frame data is writable */
|
||||
if (check_err(av_frame_make_writable(fFrame))) {
|
||||
return false;
|
||||
|
@ -28,21 +28,15 @@ public:
|
||||
~SkVideoEncoder();
|
||||
|
||||
/**
|
||||
* Begina a new recording. Balance this (after adding all of your frames) with a call
|
||||
* Begins a new recording. Balance this (after adding all of your frames) with a call
|
||||
* to endRecording().
|
||||
*/
|
||||
bool beginRecording(SkISize, int fps);
|
||||
|
||||
/**
|
||||
* Returns the preferred ImageInfo for this recording. Only valid if beginRecording() has
|
||||
* been called, and endRecording has not been called (yet).
|
||||
*/
|
||||
SkImageInfo preferredInfo() const { return fInfo; }
|
||||
|
||||
/**
|
||||
* If you have your own pixmap, call addFrame(). Note this may fail if it uses an unsupported
|
||||
* ColorType or AlphaType, or the dimensions don't match those set in beginRecording.
|
||||
* For best results, use the SkImageInfo returned by preferredInfo().
|
||||
* ColorType (requires kN32_SkColorType) or AlphaType, or the dimensions don't match those set
|
||||
* in beginRecording.
|
||||
*/
|
||||
bool addFrame(const SkPixmap&);
|
||||
|
||||
|
@ -173,7 +173,7 @@ private:
|
||||
const sk_sp<SkSurface> fSurface;
|
||||
};
|
||||
|
||||
static std::vector<SkBitmap> gMP4Frames;
|
||||
static std::vector<sk_sp<SkImage>> gMP4Frames;
|
||||
|
||||
struct MP4Sink final : public Sink {
|
||||
explicit MP4Sink(const SkMatrix& scale_matrix)
|
||||
@ -188,9 +188,8 @@ struct MP4Sink final : public Sink {
|
||||
}
|
||||
|
||||
bool endFrame(size_t i) override {
|
||||
// SkVideoEncoder wants RGBA 8888 frames. (N32 may be RGBA 8888 or BGRA 8888.)
|
||||
gMP4Frames[i].allocPixels(fSurface->imageInfo().makeColorType(kRGBA_8888_SkColorType));
|
||||
return fSurface->readPixels(gMP4Frames[i].pixmap(), 0,0);
|
||||
gMP4Frames[i] = fSurface->makeImageSnapshot();
|
||||
return SkToBool(gMP4Frames[i]);
|
||||
}
|
||||
|
||||
const sk_sp<SkSurface> fSurface;
|
||||
@ -344,9 +343,14 @@ int main(int argc, char** argv) {
|
||||
#if defined(HAVE_VIDEO_ENCODER)
|
||||
if (FLAGS_format.contains("mp4")) {
|
||||
SkVideoEncoder enc;
|
||||
enc.beginRecording({FLAGS_width, FLAGS_height}, FLAGS_fps);
|
||||
for (const SkBitmap& frame : gMP4Frames) {
|
||||
enc.addFrame(frame.pixmap());
|
||||
if (!enc.beginRecording({FLAGS_width, FLAGS_height}, FLAGS_fps)) {
|
||||
SkDEBUGF("Invalid video stream configuration.\n");
|
||||
return -1;
|
||||
}
|
||||
for (const auto& frame : gMP4Frames) {
|
||||
SkPixmap pm;
|
||||
SkAssertResult(frame->peekPixels(&pm));
|
||||
enc.addFrame(pm);
|
||||
}
|
||||
sk_sp<SkData> mp4 = enc.endRecording();
|
||||
|
||||
|
@ -100,11 +100,14 @@ int main(int argc, char** argv) {
|
||||
sk_sp<SkSurface> surf;
|
||||
sk_sp<SkData> data;
|
||||
|
||||
const auto info = SkImageInfo::MakeN32Premul(dim);
|
||||
do {
|
||||
double loop_start = SkTime::GetSecs();
|
||||
|
||||
encoder.beginRecording(dim, fps);
|
||||
auto info = encoder.preferredInfo();
|
||||
if (!encoder.beginRecording(dim, fps)) {
|
||||
SkDEBUGF("Invalid video stream configuration.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// lazily allocate the surfaces
|
||||
if (!surf) {
|
||||
|
Loading…
Reference in New Issue
Block a user