| 1405 | } |
| 1406 | |
| 1407 | int encode_avcodec(int64_t frame_nr, avcodec_encode_session_t &session, safe::mail_raw_t::queue_t<packet_t> &packets, void *channel_data, std::optional<std::chrono::steady_clock::time_point> frame_timestamp) { |
| 1408 | auto &frame = session.device->frame; |
| 1409 | frame->pts = frame_nr; |
| 1410 | |
| 1411 | auto &ctx = session.avcodec_ctx; |
| 1412 | |
| 1413 | auto &sps = session.sps; |
| 1414 | auto &vps = session.vps; |
| 1415 | |
| 1416 | // send the frame to the encoder |
| 1417 | auto ret = avcodec_send_frame(ctx.get(), frame); |
| 1418 | if (ret < 0) { |
| 1419 | char err_str[AV_ERROR_MAX_STRING_SIZE] {0}; |
| 1420 | BOOST_LOG(error) << "Could not send a frame for encoding: "sv << av_make_error_string(err_str, AV_ERROR_MAX_STRING_SIZE, ret); |
| 1421 | |
| 1422 | return -1; |
| 1423 | } |
| 1424 | |
| 1425 | while (ret >= 0) { |
| 1426 | auto packet = std::make_unique<packet_raw_avcodec>(); |
| 1427 | auto av_packet = packet.get()->av_packet; |
| 1428 | |
| 1429 | ret = avcodec_receive_packet(ctx.get(), av_packet); |
| 1430 | if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { |
| 1431 | return 0; |
| 1432 | } else if (ret < 0) { |
| 1433 | return ret; |
| 1434 | } |
| 1435 | |
| 1436 | if (av_packet->flags & AV_PKT_FLAG_KEY) { |
| 1437 | BOOST_LOG(debug) << "Frame "sv << frame_nr << ": IDR Keyframe (AV_FRAME_FLAG_KEY)"sv; |
| 1438 | } |
| 1439 | |
| 1440 | if ((frame->flags & AV_FRAME_FLAG_KEY) && !(av_packet->flags & AV_PKT_FLAG_KEY)) { |
| 1441 | BOOST_LOG(error) << "Encoder did not produce IDR frame when requested!"sv; |
| 1442 | } |
| 1443 | |
| 1444 | if (session.inject) { |
| 1445 | if (session.inject == 1) { |
| 1446 | auto h264 = cbs::make_sps_h264(ctx.get(), av_packet); |
| 1447 | |
| 1448 | sps = std::move(h264.sps); |
| 1449 | } else { |
| 1450 | auto hevc = cbs::make_sps_hevc(ctx.get(), av_packet); |
| 1451 | |
| 1452 | sps = std::move(hevc.sps); |
| 1453 | vps = std::move(hevc.vps); |
| 1454 | |
| 1455 | session.replacements.emplace_back( |
| 1456 | std::string_view((char *) std::begin(vps.old), vps.old.size()), |
| 1457 | std::string_view((char *) std::begin(vps._new), vps._new.size()) |
| 1458 | ); |
| 1459 | } |
| 1460 | |
| 1461 | session.inject = 0; |
| 1462 | |
| 1463 | session.replacements.emplace_back( |
| 1464 | std::string_view((char *) std::begin(sps.old), sps.old.size()), |
no test coverage detected