Android Native draw a window

拿到繪制好的buffer,并調用native繪制接口

        void *base;
        result = outBuffer->lock(android::GraphicBuffer::USAGE_SW_READ_OFTEN,
                                                 &base);
        if (base == nullptr || result != 0) {
            RTC_LOG(LS_INFO) << "Webrtc onFrameCallback base null";
            return;
        }
        client_->onFrameCaptured(reinterpret_cast<uint8_t *>(base),outBuffer->getStride(),region);
        outBuffer->unlock();

進行native繪制

void onFrameCaptured(uint8_t *data,int srcStride,Region &changeRegion);

void AndroidCallClient::onFrameCaptured(uint8_t *data, int srcStride, Region &changedRegion) {
        //webrtc::MutexLock lock(&pc_mutex_);
        ANativeWindow_Buffer outBuffer;
        int surfaceWidth = mRight - mLeft;
        int surfaceHeight = mBottom - mTop;
        if (mDisplayWidth <= 0) {
            return;
        }
        {
            webrtc::MutexLock lock(&pc_mutex_);
            if (!allowDrawPicture) {
                return;
            }
        }

        if (nativeWindow == nullptr) {
            return;
        }
        ANativeWindow_setBuffersGeometry(nativeWindow, surfaceWidth, surfaceHeight,
                                         WINDOW_FORMAT_RGBA_8888);
        ANativeWindow_acquire(nativeWindow);
        if (ANativeWindow_lock(nativeWindow, &outBuffer, nullptr) < 0) {
            ANativeWindow_release(nativeWindow);
            nativeWindow = nullptr;
            return;
        }

        //draw picture
        uint8_t *dst_data = static_cast<uint8_t *>(outBuffer.bits);
        int srcLineSize = srcStride * 4;
        int dstLineSize = outBuffer.stride * 4;
        libyuv::ARGBScale(data,
                          srcLineSize,
                          mDisplayWidth,
                          mDisplayHeight,
                          dst_data,
                          dstLineSize,
                          surfaceWidth,
                          surfaceHeight,
                          libyuv::kFilterNone);

        //draw red rect
        size_t count = 0;
        int alpha = 0xFF;
        int red = 0xFF;
        int green = 0x00;
        int blue = 0x00;
        int colorABGR = (alpha << 24) | (blue << 16) | (green << 8) | red;
        int x, y, left, top, right, bottom;
        const Rect *allRects = changedRegion.getArray(&count);
        if (count > 0) {
            float wRatio = surfaceWidth * 1.0 / mDisplayWidth;
            float hRatio = surfaceHeight * 1.0 / mDisplayHeight;
            RTC_LOG(LS_ERROR)
            << "rect count:" << count << ",wRatio:" << wRatio << ",hRatio:" << hRatio;
            for (int i = 0; i < count; i++) {
                Rect rect = allRects[i];
                if ((rect.left < 0 || rect.right <= 0 || rect.top < 0 || rect.bottom <= 0)
                    || (rect.right <= rect.left)
                    || (rect.bottom <= rect.top)) {
                    RTC_LOG(LS_ERROR) << "invalid rect,ignore";
                    continue;
                }
                left = (int) (rect.left * wRatio);
                top = (int) (rect.top * hRatio);
                right = (int) (rect.right * wRatio);
                bottom = (int) (rect.bottom * hRatio);
                if (right >= surfaceWidth) right = surfaceWidth - 1;
                if (bottom >= surfaceHeight) bottom = surfaceHeight - 1;

                //draw RED rectangle
                uint32_t *line = (uint32_t *) outBuffer.bits;

                //move buffer's Y position to top
                for (y = 0; y < top; y++) {
                    line = line + outBuffer.stride;
                }

                //top border
                for (x = left; x < right; x++) {
                    line[x] = colorABGR;
                }

                for (y = top; y < bottom; y++) {
                    line[left] = colorABGR;  //left border
                    line[right] = colorABGR;  //right border
                    line = line + outBuffer.stride;
                }

                //bottom border
                for (x = left; x < right; x++) {
                    line[x] = colorABGR;
                }
            }
        }

        if (ANativeWindow_unlockAndPost(nativeWindow) < 0) {
            RTC_LOG(LS_ERROR) << "ANativeWindow_unlockAndPost failed";
        }
    }

release native window

void releaseNativeWindow(JNIEnv* env);
void AndroidCallClient::releaseNativeWindow(JNIEnv *env) {
        webrtc::MutexLock lock(&pc_mutex_);

        if (false) {
            RTC_LOG(LS_WARNING) << "begin to download leak stack.";
            leaktracer::MemoryTrace::GetInstance().stopAllMonitoring();
            std::ofstream out;
            out.open("/sdcard/leaktracer.log", std::ios_base::out);

            if (out.is_open()) {
                leaktracer::MemoryTrace::GetInstance().writeLeaks(out);
            } else {
                RTC_LOG(LS_WARNING) << "Failed to write to /sdcard/leaktracer.log.";
            }
        }

        allowDrawPicture = false;
        RTC_LOG(LS_INFO) << "releaseNativeWindow";
        if (nativeWindow != nullptr) {
            RTC_LOG(LS_INFO) << "ANativeWindow_release ";
            ANativeWindow_release(nativeWindow);
            nativeWindow = nullptr;
        }
    }

setsurface init native window

void AndroidCallClient::SetSurface(JNIEnv *env,
                                       jobject surface,
                                       jint format,
                                       jint left,
                                       jint top,
                                       jint right,
                                       jint bottom,
                                       jint displayWidth,
                                       jint displayHeight) {
        RTC_LOG(LS_INFO)
        << "SetSurface:" << format << "," << left << "," << top << "," << right << "," << bottom
        << "," << displayWidth << "," << displayHeight;
        {
            webrtc::MutexLock lock(&pc_mutex_);
            allowDrawPicture = false;
        }
        if ((right - left) > displayWidth / 2) {
            RTC_LOG(LS_ERROR) << "surface is not determined,ignore";
            return;
        }
        if (nativeWindow != nullptr) {
            RTC_LOG(LS_INFO) << "ANativeWindow_release ";
            ANativeWindow_release(nativeWindow);
            nativeWindow = nullptr;
        }
        nativeWindow = ANativeWindow_fromSurface(env, surface);
        mLeft = left;
        mTop = top;
        mRight = right;
        mBottom = bottom;
        mFormat = format;
        mDisplayWidth = displayWidth;
        mDisplayHeight = displayHeight;
        {
            webrtc::MutexLock lock(&pc_mutex_);
            allowDrawPicture = true;
        }
        RTC_LOG(LS_INFO)
        << "set native Window:" << "width:" << (mRight - mLeft) << ",height:" << (mBottom - mTop);
    }

釋放資源

        if (nativeWindow != nullptr) {
           ANativeWindow_release(nativeWindow);
           nativeWindow = nullptr;
        }
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,837評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,196評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,688評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,654評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,456評論 6 406
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,955評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,044評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,195評論 0 287
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,725評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,608評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,802評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,318評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,048評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,422評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,673評論 1 281
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,424評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,762評論 2 372

推薦閱讀更多精彩內容