FFmpeg/OpenCV 实现全屏斜体水印( 二 )

< 0)goto end;while (ret >= 0) {ret = avcodec_receive_frame(deCodecCtx, frame);if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {break;}else if (ret < 0) {goto end;}// solove [libx264 @ 0x34b88a0] specified frame type (3) at 0 is not compatible with keyframe intervalframe->pict_type = AV_PICTURE_TYPE_NONE;// overlay italic txt infoAVFrame* overlay_frame = overlay(frame);if (overlay_frame == nullptr)goto end;ret = encode_frame_to_write_file(enCodecCtx, overlay_frame, pkt, ifmtCtx->streams[vistream]->time_base, ofmtCtx->streams[vostream]->time_base, ofmtCtx);if (ret < 0) {av_frame_free(&overlay_frame);goto end;}av_packet_unref(pkt);av_frame_unref(frame);av_frame_unref(overlay_frame);}#pragma endregionav_packet_unref(pkt);}...}

FFmpeg/OpenCV 实现全屏斜体水印

文章插图
思路代码 创建斜体水印
int init_water_mark(const std::string& txt, cv::Mat& water) {// 原图宽高int imageW = italicTextInfo_.frameWidth / italicTextInfo_.col;int imageH = italicTextInfo_.frameHeight / italicTextInfo_.row;cv::Mat canvasMat = cv::Mat::zeros(cv::Size(imageW, imageH), CV_8UC3);// 水印,使用 Times New Roman 字体VTText::putTextHuskyC(canvasMat, txt.c_str(), cv::Scalar(255, 255, 255), kFontSize, "Times New Roman", false, false);// 实际显示的水印行列数int w_count = italicTextInfo_.col * 2 - 1;int h_count = italicTextInfo_.row * 2;// 垂直拼接水印std::vector vImgs;cv::Mat vResult;for (int vi = 0; vi < h_count; vi++)vImgs.push_back(canvasMat);vconcat(vImgs, vResult);// 水平拼接水印std::vector hImgs;cv::Mat hResult;for (int hi = 0; hi < w_count; hi++)hImgs.push_back(vResult);hconcat(hImgs, hResult);cv::Point2f center(hResult.cols / 2.0, hResult.rows / 2.0);// 通过仿射变换将水印旋转45度,实现全屏斜体效果cv::Mat rotation_matix = getRotationMatrix2D(center, italicTextInfo_.italicAngel, 1.0);cv::Mat rotated_image;warpAffine(hResult, rotated_image, rotation_matix, hResult.size());// 然后将水印图裁剪成原图大小,用于后续叠加到原图上.water = rotated_image(cv::Rect((hResult.cols - italicTextInfo_.frameWidth) / 2, (hResult.rows - italicTextInfo_.frameHeight) / 2, italicTextInfo_.frameWidth, italicTextInfo_.frameHeight));return 0;}// 将水印图叠加到原图上// frame: 解码帧 avframe AVFrame* overlayItalicTextInfoCVCanvas(AVFrame* frame) {//cv::Mat src_mat;//frame_to_mat(frame, src_mat);int pktSize;uint8_t* buffer_rgb = convertRgb(frame, frame->width, frame->height, AV_PIX_FMT_YUV420P, frame->width, frame->height, AV_PIX_FMT_BGR24, pktSize);cv::Mat src_mat = cv::Mat(frame->height, frame->width, CV_8UC3, buffer_rgb);cv::Mat roi;roi = src_mat(cv::Rect(0, 0, watermark_.cols, watermark_.rows));cv::addWeighted(roi, 1.0, watermark_, italicTextInfo_.alpha, 0, roi);AVFrame* dst = mat_to_frame(src_mat, src_mat.cols, src_mat.rows, AV_PIX_FMT_YUV420P);if (buffer_rgb != nullptr)av_free(buffer_rgb);returndst;}
大概流程
void xxxxx(){...// 先创建个带有斜体水印的matcv::Mat water;const std::string txt = "12321321";init_water_mark(txt, water)...while (true){ret = av_read_frame(ifmtCtx, pkt);if (ret < 0)goto end;// audioif (pkt->stream_index == aistream) {av_packet_unref(pkt);continue;}// decode encode pktret = avcodec_send_packet(deCodecCtx, pkt);if (ret < 0)goto end;while (ret >= 0) {ret = avcodec_receive_frame(deCodecCtx, frame);if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {break;}else if (ret < 0) {goto end;}// solove [libx264 @ 0x34b88a0] specified frame type (3) at 0 is not compatible with keyframe intervalframe->pict_type = AV_PICTURE_TYPE_NONE;// overlay italic txt infoAVFrame* overlay_frame = overlayItalicTextInfo(frame);if (overlay_frame == nullptr)goto end;ret = encode_frame_to_write_file(enCodecCtx, overlay_frame, pkt, ifmtCtx->streams[vistream]->time_base, ofmtCtx->streams[vostream]->time_base, ofmtCtx);if (ret < 0) {av_frame_free(&overlay_frame);goto end;}av_packet_unref(pkt);av_frame_unref(frame);av_frame_unref(overlay_frame);}#pragma endregionav_packet_unref(pkt);}...}