| 518 | } |
| 519 | |
| 520 | void ScreenRecorder::record() { |
| 521 | traceScope(); |
| 522 | logln("started capturing: rectangle " << m_captureRect.getX() << "," << m_captureRect.getY() << ":" |
| 523 | << m_captureRect.getWidth() << "x" << m_captureRect.getHeight() << " scale *" |
| 524 | << m_scale << " <- input rectange " << m_captureCodecCtx->width << "x" |
| 525 | << m_captureCodecCtx->height << ", codecs: in=" << m_captureCodec->name |
| 526 | << " out=" << m_outputCodec->name); |
| 527 | auto durationPkt = TimeStatistic::getDuration("screen-pkt"); |
| 528 | auto durationScale = TimeStatistic::getDuration("screen-scale"); |
| 529 | auto durationEnc = TimeStatistic::getDuration("screen-enc"); |
| 530 | int initalFramesToSkip = 3; // avoid flickering at switching between plugins when an editor is initailly painting |
| 531 | int retRDF; |
| 532 | do { |
| 533 | retRDF = av_read_frame(m_captureFmtCtx, m_capturePacket); |
| 534 | if (retRDF == 0) { |
| 535 | if (m_capturePacket->stream_index == m_captureStreamIndex) { |
| 536 | durationPkt.reset(); |
| 537 | int retSDP = avcodec_send_packet(m_captureCodecCtx, m_capturePacket); |
| 538 | if (retSDP < 0) { |
| 539 | logError("record: avcodec_send_packet failed: err = " + String(retSDP)); |
| 540 | break; |
| 541 | } |
| 542 | int retRCF; |
| 543 | do { |
| 544 | retRCF = avcodec_receive_frame(m_captureCodecCtx, m_captureFrame); |
| 545 | if (retRCF == 0) { |
| 546 | auto* frame = m_captureFrame; |
| 547 | if (m_captureFrame->width != m_cropFrame->width || |
| 548 | m_captureFrame->height != m_cropFrame->height) { |
| 549 | // crop the frame to the window dimension |
| 550 | bool cropErr = false; |
| 551 | for (int y = m_captureRect.getY(); y < m_captureRect.getBottom(); y++) { |
| 552 | auto* src = m_captureFrame->data[0] + m_captureFrame->linesize[0] * y + |
| 553 | m_captureRect.getX() * m_pxSize; |
| 554 | auto* dst = |
| 555 | m_cropFrame->data[0] + m_cropFrame->linesize[0] * (y - m_captureRect.getY()); |
| 556 | if (nullptr != src && nullptr != dst) { |
| 557 | memcpy(dst, src, (size_t)m_cropFrame->linesize[0]); |
| 558 | } else { |
| 559 | cropErr = true; |
| 560 | break; |
| 561 | } |
| 562 | } |
| 563 | if (cropErr) { |
| 564 | continue; |
| 565 | } |
| 566 | frame = m_cropFrame; |
| 567 | } |
| 568 | |
| 569 | // convert pixel format |
| 570 | durationScale.reset(); |
| 571 | sws_scale(m_swsCtx, frame->data, frame->linesize, 0, frame->height, m_outputFrame->data, |
| 572 | m_outputFrame->linesize); |
| 573 | durationScale.update(); |
| 574 | |
| 575 | // convert to WEBP |
| 576 | durationEnc.reset(); |
| 577 | int retSDF = avcodec_send_frame(m_outputCodecCtx, m_outputFrame); |