Krita Source Code Documentation
Loading...
Searching...
No Matches
KisAndroidMediaEncoderRunnable Class Reference

#include <KisAndroidMediaEncoderRunnable.h>

+ Inheritance diagram for KisAndroidMediaEncoderRunnable:

Classes

class  Context
 
struct  EncoderImage
 
class  Format
 

Static Public Member Functions

static KisAndroidMediaEncoderRunnablecreate (const KisMediaEncoderWrapperSettings &settings, QObject *parent=nullptr)
 
static void getSupportedFormats (QVector< KisMediaEncoderFormat * > &outSupportedFormats)
 

Protected Member Functions

EncodeResult encode (QString &outErrorMessage) override
 
 KisAndroidMediaEncoderRunnable (const KisMediaEncoderWrapperSettings &settings, QObject *parent)
 
- Protected Member Functions inherited from KisMediaEncoderRunnable
bool isCancelled () const
 
 KisMediaEncoderRunnable (const KisMediaEncoderWrapperSettings &settings, QObject *parent)
 
bool nextFrame (Frame &outFrame)
 
const KisMediaEncoderWrapperSettings settings ()
 

Private Member Functions

bool copyTemporaryToOutputFile (Context &ctx, const QString &tempPath, const QString &outputPath)
 
int drain (Context &ctx, long long initialTimeout)
 
EncodeResult prepare (Context &ctx)
 

Static Private Member Functions

static void checkFormatSupport (Context &ctx, int formatId, QVector< KisMediaEncoderFormat * > &outSupportedFormats)
 
static bool readEncoderImage (Context &ctx, EncoderImage &outImage)
 
static bool readPlaneBuffer (Context &ctx, int index, uint8_t *&outBuffer)
 
static bool readPlanePixelStride (Context &ctx, int index, int &outPixelStride)
 
static bool readPlaneRowStride (Context &ctx, int index, int &outRowStride)
 

Static Private Attributes

static constexpr int DRAIN_CANCELLED = -3
 
static constexpr int DRAIN_END_OF_STREAM = -1
 
static constexpr int DRAIN_ERROR = -2
 
static constexpr int FORMAT_MP4_AV1 = 2
 
static constexpr int FORMAT_MP4_H264 = 0
 
static constexpr int FORMAT_WEBM_VP8 = 1
 
static constexpr int STATUS_END_OF_STREAM = 2
 
static constexpr int STATUS_ERROR_DRAIN_MUXER_ADD_TRACK = 404
 
static constexpr int STATUS_ERROR_START_ENCODER = 104
 
static constexpr int STATUS_NEEDS_COPY = 3
 
static constexpr int STATUS_OK = 0
 
static constexpr int STATUS_TIMEOUT = 1
 

Additional Inherited Members

- Public Slots inherited from KisMediaEncoderRunnable
void slotHandleCancelRequested ()
 
- Signals inherited from KisMediaEncoderRunnable
void sigCancelled ()
 
void sigCompleted ()
 
void sigFailed (const QString &errorMessage)
 
void sigProgressUpdated (int frameNo)
 
void sigStarted ()
 
- Public Member Functions inherited from KisMediaEncoderRunnable
void run () override
 
- Protected Types inherited from KisMediaEncoderRunnable
enum class  EncodeResult { Completed , Cancelled , Failed }
 

Detailed Description

Definition at line 13 of file KisAndroidMediaEncoderRunnable.h.

Constructor & Destructor Documentation

◆ KisAndroidMediaEncoderRunnable()

KisAndroidMediaEncoderRunnable::KisAndroidMediaEncoderRunnable ( const KisMediaEncoderWrapperSettings & settings,
QObject * parent )
protected

Definition at line 405 of file KisAndroidMediaEncoderRunnable.cpp.

408{
409}
KisMediaEncoderRunnable(const KisMediaEncoderWrapperSettings &settings, QObject *parent)
const KisMediaEncoderWrapperSettings settings()

Member Function Documentation

◆ checkFormatSupport()

void KisAndroidMediaEncoderRunnable::checkFormatSupport ( Context & ctx,
int formatId,
QVector< KisMediaEncoderFormat * > & outSupportedFormats )
staticprivate

Definition at line 849 of file KisAndroidMediaEncoderRunnable.cpp.

852{
853 QJniObject supports = QJniObject::callStaticObjectMethod("org/krita/android/VideoEncoder",
854 "getSupportsForFormat",
855 "(I)Ljava/util/List;",
856 jint(formatId));
857 if (ctx.checkObject(QStringLiteral("supports"), supports)) {
858 return;
859 }
860
861 jint count = supports.callMethod<jint>("size", "()I");
862 if (ctx.checkException(QStringLiteral("size"))) {
863 return;
864 }
865
867 for (jint i = 0; i < count; ++i) {
868 QJniObject entry = supports.callObjectMethod("get", "(I)Ljava/lang/Object;", i);
869 if (ctx.checkObject(QStringLiteral("entry"), entry)) {
870 continue;
871 }
872
873 QJniObject name = entry.getObjectField("name", "Ljava/lang/String;");
874 if (ctx.checkObject(QStringLiteral("name"), name)) {
875 continue;
876 }
877
878 QString nameString = name.toString();
879 if (ctx.checkException(QStringLiteral("nameString")) || nameString.isEmpty()) {
880 continue;
881 }
882
883 bool hardware = entry.getField<jboolean>("hardware");
884 if (ctx.checkException(QStringLiteral("hardware"))) {
885 continue;
886 }
887
888 encoders.append({nameString, hardware});
889 }
890
891 if (!encoders.isEmpty()) {
892 outSupportedFormats.append(new Format(formatId, encoders));
893 }
894}
const char * name(StandardAction id)

References KisAndroidMediaEncoderRunnable::Context::checkException(), and KisAndroidMediaEncoderRunnable::Context::checkObject().

◆ copyTemporaryToOutputFile()

bool KisAndroidMediaEncoderRunnable::copyTemporaryToOutputFile ( Context & ctx,
const QString & tempPath,
const QString & outputPath )
private

Definition at line 740 of file KisAndroidMediaEncoderRunnable.cpp.

743{
744 QFile tempFile(tempPath);
745 if (!tempFile.open(QIODevice::ReadOnly)) {
746 ctx.setInternalErrorMessage(
747 QStringLiteral("failed to open temp file '%1': %2").arg(tempPath).arg(tempFile.errorString()));
748 return false;
749 }
750
751 QFile outputFile(outputPath);
752 if (!outputFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
753 ctx.setInternalErrorMessage(
754 QStringLiteral("failed to open output file '%1': %2").arg(outputPath).arg(outputFile.errorString()));
755 return false;
756 }
757
758 QByteArray buffer;
759 buffer.resize(BUFSIZ);
760 while (true) {
761 qint64 read = tempFile.read(buffer.data(), BUFSIZ);
762 if (read < 0) {
763 ctx.setInternalErrorMessage(
764 QStringLiteral("failed to read from temp file '%1': %2").arg(tempPath).arg(tempFile.errorString()));
765 return false;
766 } else if (read > 0) {
767 qint64 written = outputFile.write(buffer, read);
768 if (written < 0) {
769 ctx.setInternalErrorMessage(QStringLiteral("failed to write %1 byte(s) to output file '%2': %3")
770 .arg(read)
771 .arg(outputPath)
772 .arg(outputFile.errorString()));
773 return false;
774 } else if (written != read) {
775 ctx.setInternalErrorMessage(
776 QStringLiteral("tried to write %1 byte(s) to output file '%2', but only wrote %3")
777 .arg(read)
778 .arg(outputPath)
779 .arg(written));
780 return false;
781 }
782 } else {
783 if (outputFile.flush()) {
784 return true;
785 } else {
786 ctx.setInternalErrorMessage(QStringLiteral("failed to flush output file '%1': %2")
787 .arg(outputPath)
788 .arg(outputFile.errorString()));
789 return false;
790 }
791 }
792 }
793}

References KisAndroidMediaEncoderRunnable::Context::setInternalErrorMessage().

◆ create()

KisAndroidMediaEncoderRunnable * KisAndroidMediaEncoderRunnable::create ( const KisMediaEncoderWrapperSettings & settings,
QObject * parent = nullptr )
static

◆ drain()

int KisAndroidMediaEncoderRunnable::drain ( Context & ctx,
long long initialTimeout )
private

Definition at line 712 of file KisAndroidMediaEncoderRunnable.cpp.

713{
714 int count = 0;
715 long long timeout = initialTimeout;
716 while (true) {
717 if (isCancelled()) {
718 return DRAIN_CANCELLED;
719 }
720
721 int drainResult = int(ctx.encoder().callMethod<jint>("drain", "(J)I", jlong(timeout)));
722
723 if (ctx.checkResult(QStringLiteral("drain"), drainResult)) {
724 return DRAIN_ERROR;
725
726 } else if (drainResult == STATUS_TIMEOUT) {
727 break;
728
729 } else if (drainResult == STATUS_END_OF_STREAM) {
730 return DRAIN_END_OF_STREAM;
731
732 } else {
734 ++count;
735 }
736 }
737 return count;
738}
#define KIS_SAFE_ASSERT_RECOVER_NOOP(cond)
Definition kis_assert.h:130

References KisAndroidMediaEncoderRunnable::Context::checkResult(), DRAIN_CANCELLED, DRAIN_END_OF_STREAM, DRAIN_ERROR, KisAndroidMediaEncoderRunnable::Context::encoder(), KisMediaEncoderRunnable::isCancelled(), KIS_SAFE_ASSERT_RECOVER_NOOP, STATUS_END_OF_STREAM, STATUS_OK, and STATUS_TIMEOUT.

◆ encode()

KisMediaEncoderRunnable::EncodeResult KisAndroidMediaEncoderRunnable::encode ( QString & outErrorMessage)
overrideprotectedvirtual

Implements KisMediaEncoderRunnable.

Definition at line 411 of file KisAndroidMediaEncoderRunnable.cpp.

412{
413 Format *format = static_cast<Format *>(settings().format);
414
415 QTemporaryFile tempFile;
416 QString tempFilePath;
417 if (tempFile.open()) {
418 tempFilePath = tempFile.fileName();
419 tempFile.close();
420 } else {
421 warnFile << "Failed to open temporary file:" << tempFile.errorString();
422 // Keep going, we might not actually need a temporary file.
423 }
424
425 Context ctx(&outErrorMessage);
426 int outputWidth = settings().outputSize.width();
427 int outputHeight = settings().outputSize.height();
428
429 // Set up the encoder.
430 {
431 QJniObject outputPath = QJniObject::fromString(settings().outputFile);
432 if (ctx.checkObject(QStringLiteral("outputPath"), outputPath)) {
434 }
435
436 QJniObject tempPath = QJniObject::fromString(tempFilePath);
437 if (ctx.checkObject(QStringLiteral("tempPath"), tempPath)) {
439 }
440
441 QJniObject encoderName = QJniObject::fromString(format->getEncoderPreference(settings().formatPreferences));
442 ctx.checkException(QStringLiteral("encoderName"));
443
444 ctx.setEncoder(QJniObject("org/krita/android/VideoEncoder",
445 "(IIIFLjava/lang/String;Ljava/lang/String;Ljava/lang/String;I)V",
446 jint(format->formatId()),
447 jint(outputWidth),
448 jint(outputHeight),
449 jfloat(settings().outputFps),
450 outputPath.object<jstring>(),
451 tempPath.object<jstring>(),
452 encoderName.object<jstring>(),
453 jint(format->getBitratePreference(settings().formatPreferences))));
454 if (ctx.checkObject(QStringLiteral("encoder"), ctx.encoder())) {
456 }
457 }
458
459 if (isCancelled()) {
461 }
462
463 // Start the encoding.
464 {
465 QJniObject activity = QJniObject::callStaticObjectMethod("org/qtproject/qt5/android/QtNative",
466 "activity",
467 "()Landroid/app/Activity;");
468 if (ctx.checkObject(QStringLiteral("activity"), activity)) {
470 }
471
472 int startResult =
473 int(ctx.encoder().callMethod<jint>("start", "(Landroid/content/Context;)I", activity.object<jobject>()));
474 if (ctx.checkResult(QStringLiteral("start"), startResult)) {
476 }
477 }
478
479 // Encode the frames.
480 Frame frame;
481 while (nextFrame(frame)) {
482 if (isCancelled()) {
484 }
485
486 // Grab the next frame from disk.
487 QImage inputImage;
488 AVPixelFormat inputPixelFormat;
489 if (frame.readImage(inputImage)) {
490 switch (inputImage.format()) {
491 case QImage::Format_RGB32:
492 inputPixelFormat = AV_PIX_FMT_BGR0;
493 break;
494 case QImage::Format_ARGB32:
495 inputPixelFormat = AV_PIX_FMT_BGRA;
496 break;
497 default:
498 // The above are the only formats I can get the the recorder to
499 // produce, so I'm not gonna get experimental with this.
500 inputPixelFormat = AV_PIX_FMT_BGRA;
501 inputImage = inputImage.convertToFormat(QImage::Format_ARGB32);
502 if (inputImage.isNull()) {
503 warnFile << "Frame conversion from" << inputImage.format() << "failed";
504 continue;
505 }
506 break;
507 }
508 } else {
509 continue; // Keep going, some frames may be corrupted.
510 }
511
512 int instances = frame.instances();
513 for (int i = 0; i < instances; ++i) {
514 // Grab a buffer from the encoder.
515 EncodeResult prepareResult = prepare(ctx);
516 if (prepareResult != EncodeResult::Completed) {
517 return prepareResult;
518 }
519
520 // Retrieve the buffer layout.
521 EncoderImage encoderImage;
522 if (!readEncoderImage(ctx, encoderImage)) {
524 }
525
526 // Map the buffer layout to a libswscale-befitting arrangement. The
527 // layout may either have the YUV components in separate buffers or it
528 // may have the U and V components combined into a single buffer, where
529 // either U or V can come first. Which one we get depends on hardware.
530 uint8_t *dstBuffers[4] = {nullptr, nullptr, nullptr, nullptr};
531 int dstLinesizes[4] = {0, 0, 0, 0};
532 AVPixelFormat outputPixelFormat;
533 if (encoderImage.pixelStrideU == 1 && encoderImage.pixelStrideV == 1) {
534 // Separate Y, U and V buffers.
535 outputPixelFormat = AV_PIX_FMT_YUV420P;
536 dstBuffers[0] = encoderImage.bufferY;
537 dstBuffers[1] = encoderImage.bufferU;
538 dstBuffers[2] = encoderImage.bufferV;
539 dstLinesizes[0] = encoderImage.rowStrideY;
540 dstLinesizes[1] = encoderImage.rowStrideU;
541 dstLinesizes[2] = encoderImage.rowStrideV;
542
543 } else if (encoderImage.pixelStrideU == 2 && encoderImage.pixelStrideV == 2
544 && encoderImage.bufferU + 1 == encoderImage.bufferV) {
545 // One Y buffer and one combined UV buffer, U comes first.
546 outputPixelFormat = AV_PIX_FMT_NV12;
547 dstBuffers[0] = encoderImage.bufferY;
548 dstBuffers[1] = encoderImage.bufferU;
549 dstLinesizes[0] = encoderImage.rowStrideY;
550 dstLinesizes[1] = encoderImage.rowStrideU;
551
552 } else if (encoderImage.pixelStrideU == 2 && encoderImage.pixelStrideV == 2
553 && encoderImage.bufferV + 1 == encoderImage.bufferU) {
554 // One Y buffer and one combined UV buffer, V comes first.
555 outputPixelFormat = AV_PIX_FMT_NV21;
556 dstBuffers[0] = encoderImage.bufferY;
557 dstBuffers[1] = encoderImage.bufferV;
558 dstLinesizes[0] = encoderImage.rowStrideY;
559 dstLinesizes[1] = encoderImage.rowStrideV;
560
561 } else {
562 ctx.setInternalErrorMessage(QStringLiteral("unknown buffer format u%1/%2 v%3/%4")
563 .arg(quintptr(encoderImage.bufferU), 0, 16)
564 .arg(encoderImage.pixelStrideU)
565 .arg(quintptr(encoderImage.bufferV), 0, 16)
566 .arg(encoderImage.pixelStrideV));
568 }
569
570 SwsContext *swsContext = ctx.getSwsContextFor(inputImage.width(),
571 inputImage.height(),
572 inputPixelFormat,
573 outputWidth,
574 outputHeight,
575 outputPixelFormat,
576 SWS_FAST_BILINEAR);
577 if (!swsContext) {
578 ctx.setInternalErrorMessage(QStringLiteral("sws_getCachedContext"));
580 }
581
582 if (instances == 1) {
583 // Just a single frame, scale it into the native buffer.
584 const uint8_t *srcBuffers[] = {inputImage.bits(), nullptr, nullptr, nullptr};
585 const int srcLinesizes[] = {inputImage.bytesPerLine(), 0, 0, 0};
586 sws_scale(swsContext, srcBuffers, srcLinesizes, 0, inputImage.height(), dstBuffers, dstLinesizes);
587
588 } else {
589 // Repeated frame, scale it into an intermediate buffer, then
590 // copy it over to the native one for each instance.
591 if (i == 0 || ctx.imageFormat() != outputPixelFormat) {
592 if (ctx.imageFormat() != outputPixelFormat) {
593 if (!ctx.allocateImage(outputWidth, outputHeight, outputPixelFormat)) {
594 warnFile << "Encoder changed pixel format from" << int(ctx.imageFormat()) << "to"
595 << int(outputPixelFormat);
597 }
598 }
599
600 const uint8_t *srcBuffers[] = {inputImage.bits(), nullptr, nullptr, nullptr};
601 const int srcLinesizes[] = {inputImage.bytesPerLine(), 0, 0, 0};
602 sws_scale(swsContext,
603 srcBuffers,
604 srcLinesizes,
605 0,
606 inputImage.height(),
607 ctx.imageBuffers(),
608 ctx.imageLinesizes());
609 }
610
611 av_image_copy2(dstBuffers,
612 dstLinesizes,
613 ctx.imageBuffers(),
614 ctx.imageLinesizes(),
615 outputPixelFormat,
616 outputWidth,
617 outputHeight);
618 }
619
620 int commitResult = int(ctx.encoder().callMethod<jint>("commit", "()I"));
621 if (ctx.checkResult(QStringLiteral("commit"), commitResult)) {
623 }
624 }
625 }
626
627 if (isCancelled()) {
629 }
630
631 // Finish the encoder stream.
632 {
633 // Need a buffer from the encoder to tell it that it's done.
634 EncodeResult prepareResult = prepare(ctx);
635 if (prepareResult != EncodeResult::Completed) {
636 return prepareResult;
637 }
638 // Hand an empty buffer back with the end of stream flag set.
639 int finishResult = int(ctx.encoder().callMethod<jint>("finish", "()I"));
640 if (ctx.checkResult(QStringLiteral("finish"), finishResult)) {
642 }
643 }
644
645 // Drain all remaining frames out of the encoder.
646 while (true) {
647 int drainResult = drain(ctx, 1000000LL);
648 if (drainResult == DRAIN_END_OF_STREAM) {
649 break;
650 } else if (drainResult == DRAIN_ERROR) {
652 } else if (drainResult == DRAIN_CANCELLED) {
654 } else {
655 KIS_SAFE_ASSERT_RECOVER_NOOP(drainResult >= 0);
656 }
657 }
658
659 // Close the encoder, copy the temporary file to the output file if needed.
660 {
661 int closeResult = int(ctx.encoder().callMethod<jint>("close", "()I"));
662 if (ctx.checkResult(QStringLiteral("close"), closeResult)) {
664 }
665
666 if (isCancelled()) {
668 }
669
670 if (closeResult == STATUS_NEEDS_COPY) {
671 if (!copyTemporaryToOutputFile(ctx, tempFilePath, settings().outputFile)) {
673 }
674 }
675 }
676
678}
int drain(Context &ctx, long long initialTimeout)
static bool readEncoderImage(Context &ctx, EncoderImage &outImage)
bool copyTemporaryToOutputFile(Context &ctx, const QString &tempPath, const QString &outputPath)
bool nextFrame(Frame &outFrame)
#define warnFile
Definition kis_debug.h:95

References KisAndroidMediaEncoderRunnable::Context::allocateImage(), KisAndroidMediaEncoderRunnable::EncoderImage::bufferU, KisAndroidMediaEncoderRunnable::EncoderImage::bufferV, KisAndroidMediaEncoderRunnable::EncoderImage::bufferY, KisMediaEncoderRunnable::Cancelled, KisAndroidMediaEncoderRunnable::Context::checkException(), KisAndroidMediaEncoderRunnable::Context::checkObject(), KisAndroidMediaEncoderRunnable::Context::checkResult(), KisMediaEncoderRunnable::Completed, copyTemporaryToOutputFile(), drain(), DRAIN_CANCELLED, DRAIN_END_OF_STREAM, DRAIN_ERROR, KisAndroidMediaEncoderRunnable::Context::encoder(), KisMediaEncoderRunnable::Failed, KisMediaEncoderWrapperSettings::format, KisAndroidMediaEncoderRunnable::Format::formatId(), KisAndroidMediaEncoderRunnable::Format::getBitratePreference(), KisAndroidMediaEncoderRunnable::Format::getEncoderPreference(), KisAndroidMediaEncoderRunnable::Context::getSwsContextFor(), KisAndroidMediaEncoderRunnable::Context::imageBuffers(), KisAndroidMediaEncoderRunnable::Context::imageFormat(), KisAndroidMediaEncoderRunnable::Context::imageLinesizes(), KisMediaEncoderRunnable::Frame::instances(), KisMediaEncoderRunnable::isCancelled(), KIS_SAFE_ASSERT_RECOVER_NOOP, KisMediaEncoderRunnable::nextFrame(), KisMediaEncoderWrapperSettings::outputSize, KisAndroidMediaEncoderRunnable::EncoderImage::pixelStrideU, KisAndroidMediaEncoderRunnable::EncoderImage::pixelStrideV, prepare(), readEncoderImage(), KisMediaEncoderRunnable::Frame::readImage(), KisAndroidMediaEncoderRunnable::EncoderImage::rowStrideU, KisAndroidMediaEncoderRunnable::EncoderImage::rowStrideV, KisAndroidMediaEncoderRunnable::EncoderImage::rowStrideY, KisAndroidMediaEncoderRunnable::Context::setEncoder(), KisAndroidMediaEncoderRunnable::Context::setInternalErrorMessage(), KisMediaEncoderRunnable::settings(), STATUS_NEEDS_COPY, and warnFile.

◆ getSupportedFormats()

void KisAndroidMediaEncoderRunnable::getSupportedFormats ( QVector< KisMediaEncoderFormat * > & outSupportedFormats)
static

Definition at line 396 of file KisAndroidMediaEncoderRunnable.cpp.

397{
398 Context ctx;
399 int formatIds[] = {FORMAT_MP4_H264, FORMAT_WEBM_VP8, FORMAT_MP4_AV1};
400 for (int formatId : formatIds) {
401 checkFormatSupport(ctx, formatId, outSupportedFormats);
402 }
403}
static void checkFormatSupport(Context &ctx, int formatId, QVector< KisMediaEncoderFormat * > &outSupportedFormats)

References checkFormatSupport(), FORMAT_MP4_AV1, FORMAT_MP4_H264, and FORMAT_WEBM_VP8.

◆ prepare()

KisMediaEncoderRunnable::EncodeResult KisAndroidMediaEncoderRunnable::prepare ( Context & ctx)
private

Definition at line 680 of file KisAndroidMediaEncoderRunnable.cpp.

681{
682 while (true) {
683 if (isCancelled()) {
685 }
686
687 int prepareResult = int(ctx.encoder().callMethod<jint>("prepare", "(J)I", jlong(100000LL)));
688 if (ctx.checkResult(QStringLiteral("prepare"), prepareResult)) {
690
691 } else if (prepareResult == STATUS_TIMEOUT) {
692 int drainResult = drain(ctx, 0LL);
693 if (drainResult == DRAIN_END_OF_STREAM) {
694 ctx.setInternalErrorMessage(QStringLiteral("unexpected end of stream"));
696 } else if (drainResult == DRAIN_ERROR) {
698 } else if (drainResult == DRAIN_CANCELLED) {
700 } else {
701 KIS_SAFE_ASSERT_RECOVER_NOOP(drainResult >= 0);
702 }
703
704 } else {
705 KIS_SAFE_ASSERT_RECOVER_NOOP(prepareResult == STATUS_OK);
706 break;
707 }
708 }
710}

References KisMediaEncoderRunnable::Cancelled, KisAndroidMediaEncoderRunnable::Context::checkResult(), KisMediaEncoderRunnable::Completed, drain(), DRAIN_CANCELLED, DRAIN_END_OF_STREAM, DRAIN_ERROR, KisAndroidMediaEncoderRunnable::Context::encoder(), KisMediaEncoderRunnable::Failed, KisMediaEncoderRunnable::isCancelled(), KIS_SAFE_ASSERT_RECOVER_NOOP, KisAndroidMediaEncoderRunnable::Context::setInternalErrorMessage(), STATUS_OK, and STATUS_TIMEOUT.

◆ readEncoderImage()

bool KisAndroidMediaEncoderRunnable::readEncoderImage ( Context & ctx,
EncoderImage & outImage )
staticprivate

Definition at line 795 of file KisAndroidMediaEncoderRunnable.cpp.

796{
797 return readPlaneBuffer(ctx, 0, outImage.bufferY) && readPlaneBuffer(ctx, 1, outImage.bufferU)
798 && readPlaneBuffer(ctx, 2, outImage.bufferV) && readPlaneRowStride(ctx, 0, outImage.rowStrideY)
799 && readPlaneRowStride(ctx, 1, outImage.rowStrideU) && readPlaneRowStride(ctx, 2, outImage.rowStrideV)
800 && readPlanePixelStride(ctx, 1, outImage.pixelStrideU) && readPlanePixelStride(ctx, 2, outImage.pixelStrideV);
801}
static bool readPlaneBuffer(Context &ctx, int index, uint8_t *&outBuffer)
static bool readPlaneRowStride(Context &ctx, int index, int &outRowStride)
static bool readPlanePixelStride(Context &ctx, int index, int &outPixelStride)

References KisAndroidMediaEncoderRunnable::EncoderImage::bufferU, KisAndroidMediaEncoderRunnable::EncoderImage::bufferV, KisAndroidMediaEncoderRunnable::EncoderImage::bufferY, KisAndroidMediaEncoderRunnable::EncoderImage::pixelStrideU, KisAndroidMediaEncoderRunnable::EncoderImage::pixelStrideV, readPlaneBuffer(), readPlanePixelStride(), readPlaneRowStride(), KisAndroidMediaEncoderRunnable::EncoderImage::rowStrideU, KisAndroidMediaEncoderRunnable::EncoderImage::rowStrideV, and KisAndroidMediaEncoderRunnable::EncoderImage::rowStrideY.

◆ readPlaneBuffer()

bool KisAndroidMediaEncoderRunnable::readPlaneBuffer ( Context & ctx,
int index,
uint8_t *& outBuffer )
staticprivate

Definition at line 803 of file KisAndroidMediaEncoderRunnable.cpp.

804{
805 QJniObject plane =
806 ctx.encoder().callObjectMethod("getInputImagePlaneBuffer", "(I)Ljava/nio/ByteBuffer;", jint(index));
807 if (ctx.checkObject(QStringLiteral("plane"), plane)) {
808 return false;
809 }
810
811 uint8_t *buffer = static_cast<uint8_t *>(ctx.env()->GetDirectBufferAddress(plane.object<jobject>()));
812 if (!buffer) {
813 ctx.setInternalErrorMessage(QStringLiteral("null plane buffer %1").arg(index));
814 return false;
815 }
816
817 outBuffer = buffer;
818 return true;
819}

References KisAndroidMediaEncoderRunnable::Context::checkObject(), KisAndroidMediaEncoderRunnable::Context::encoder(), KisAndroidMediaEncoderRunnable::Context::env(), and KisAndroidMediaEncoderRunnable::Context::setInternalErrorMessage().

◆ readPlanePixelStride()

bool KisAndroidMediaEncoderRunnable::readPlanePixelStride ( Context & ctx,
int index,
int & outPixelStride )
staticprivate

Definition at line 835 of file KisAndroidMediaEncoderRunnable.cpp.

836{
837 jint pixelStride = ctx.encoder().callMethod<jint>("getInputImagePlanePixelStride", "(I)I", jint(index));
838 if (ctx.checkException(QStringLiteral("pixelStride"))) {
839 return false;
840 } else if (pixelStride <= 0) {
841 ctx.setInternalErrorMessage(QStringLiteral("invalid pixel stride %1: %2").arg(index).arg(pixelStride));
842 return false;
843 }
844
845 outPixelStride = int(pixelStride);
846 return true;
847}

References KisAndroidMediaEncoderRunnable::Context::checkException(), KisAndroidMediaEncoderRunnable::Context::encoder(), and KisAndroidMediaEncoderRunnable::Context::setInternalErrorMessage().

◆ readPlaneRowStride()

bool KisAndroidMediaEncoderRunnable::readPlaneRowStride ( Context & ctx,
int index,
int & outRowStride )
staticprivate

Definition at line 821 of file KisAndroidMediaEncoderRunnable.cpp.

822{
823 jint rowStride = ctx.encoder().callMethod<jint>("getInputImagePlaneRowStride", "(I)I", jint(index));
824 if (ctx.checkException(QStringLiteral("rowStride"))) {
825 return false;
826 } else if (rowStride <= 0) {
827 ctx.setInternalErrorMessage(QStringLiteral("invalid row stride %1: %2").arg(index).arg(rowStride));
828 return false;
829 }
830
831 outRowStride = int(rowStride);
832 return true;
833}

References KisAndroidMediaEncoderRunnable::Context::checkException(), KisAndroidMediaEncoderRunnable::Context::encoder(), and KisAndroidMediaEncoderRunnable::Context::setInternalErrorMessage().

Member Data Documentation

◆ DRAIN_CANCELLED

constexpr int KisAndroidMediaEncoderRunnable::DRAIN_CANCELLED = -3
staticconstexprprivate

Definition at line 29 of file KisAndroidMediaEncoderRunnable.h.

◆ DRAIN_END_OF_STREAM

constexpr int KisAndroidMediaEncoderRunnable::DRAIN_END_OF_STREAM = -1
staticconstexprprivate

Definition at line 27 of file KisAndroidMediaEncoderRunnable.h.

◆ DRAIN_ERROR

constexpr int KisAndroidMediaEncoderRunnable::DRAIN_ERROR = -2
staticconstexprprivate

Definition at line 28 of file KisAndroidMediaEncoderRunnable.h.

◆ FORMAT_MP4_AV1

constexpr int KisAndroidMediaEncoderRunnable::FORMAT_MP4_AV1 = 2
staticconstexprprivate

Definition at line 33 of file KisAndroidMediaEncoderRunnable.h.

◆ FORMAT_MP4_H264

constexpr int KisAndroidMediaEncoderRunnable::FORMAT_MP4_H264 = 0
staticconstexprprivate

Definition at line 31 of file KisAndroidMediaEncoderRunnable.h.

◆ FORMAT_WEBM_VP8

constexpr int KisAndroidMediaEncoderRunnable::FORMAT_WEBM_VP8 = 1
staticconstexprprivate

Definition at line 32 of file KisAndroidMediaEncoderRunnable.h.

◆ STATUS_END_OF_STREAM

constexpr int KisAndroidMediaEncoderRunnable::STATUS_END_OF_STREAM = 2
staticconstexprprivate

Definition at line 37 of file KisAndroidMediaEncoderRunnable.h.

◆ STATUS_ERROR_DRAIN_MUXER_ADD_TRACK

constexpr int KisAndroidMediaEncoderRunnable::STATUS_ERROR_DRAIN_MUXER_ADD_TRACK = 404
staticconstexprprivate

Definition at line 40 of file KisAndroidMediaEncoderRunnable.h.

◆ STATUS_ERROR_START_ENCODER

constexpr int KisAndroidMediaEncoderRunnable::STATUS_ERROR_START_ENCODER = 104
staticconstexprprivate

Definition at line 39 of file KisAndroidMediaEncoderRunnable.h.

◆ STATUS_NEEDS_COPY

constexpr int KisAndroidMediaEncoderRunnable::STATUS_NEEDS_COPY = 3
staticconstexprprivate

Definition at line 38 of file KisAndroidMediaEncoderRunnable.h.

◆ STATUS_OK

constexpr int KisAndroidMediaEncoderRunnable::STATUS_OK = 0
staticconstexprprivate

Definition at line 35 of file KisAndroidMediaEncoderRunnable.h.

◆ STATUS_TIMEOUT

constexpr int KisAndroidMediaEncoderRunnable::STATUS_TIMEOUT = 1
staticconstexprprivate

Definition at line 36 of file KisAndroidMediaEncoderRunnable.h.


The documentation for this class was generated from the following files: