#include "gen_frame.h" #include #undef min #undef max bool GenNv12Frame(ID3D11Device* device, ID3D11DeviceContext* ctx, const D3D11_TEXTURE2D_DESC& desc, ID3D11Texture2D* img, BufferFiller& buffers, AVFrame*& outFrame, D3dConverter& rgbToNv12) { winrt::com_ptr nv12Img = nullptr; if (FAILED(device->CreateTexture2D(&desc, nullptr, nv12Img.put()))) { return false; } if (!CheckHR(rgbToNv12.Convert(img, nv12Img.get()), "rgbToNv12.Convert")) { return false; } // 填充缓冲区 if (!buffers.Fill(device, desc)) { return false; } ctx->CopyResource(buffers.GetCopy(), nv12Img.get()); D3D11_MAPPED_SUBRESOURCE resource; if (!CheckHR(ctx->Map(buffers.GetMap(), 0, D3D11_MAP_READ, 0, &resource), "ID3D11DeviceContext::Map")) { return false; } auto height = std::min(outFrame->height, (int)desc.Height); auto width = outFrame->width; auto srcLinesize = resource.RowPitch; auto dstLinesize = outFrame->linesize[0]; auto srcData = (uint8_t*)resource.pData; auto titleHeight = std::max(int(desc.Height - height), 0); /* auto copyLine = std::min(std::min(width, (int) srcLinesize), dstLinesize);*/ auto border = (desc.Width - width) / 2; __mtx.lock(); // Y int Ystart = (titleHeight - border) * srcLinesize + border; auto dstData = outFrame->data[0]; for (int row = 0; row < height; ++row) { memcpy(dstData + row * dstLinesize, srcData + Ystart + row * srcLinesize, width); } // UV dstData = outFrame->data[1]; int UVStart = srcLinesize * desc.Height + (titleHeight - border) / 2 * srcLinesize + border / 2 * 2; for (int row = 0; row < height / 2; ++row) { memcpy(dstData + row * dstLinesize, srcData + UVStart + row * srcLinesize, width); } __mtx.unlock(); ctx->Unmap(buffers.GetMap(), 0); if (!buffers.Reset()) { return false; } return true; } bool GenRgbFrame(ID3D11Device* device, ID3D11DeviceContext* ctx, const D3D11_TEXTURE2D_DESC& desc, ID3D11Texture2D* img, BufferFiller& buffers, AVFrame*& outFrame) { if (!buffers.Fill(device, desc)) { return false; } ctx->CopyResource(buffers.GetCopy(), img); D3D11_MAPPED_SUBRESOURCE resource; if (!CheckHR(ctx->Map(buffers.GetMap(), 0, D3D11_MAP_READ, 0, &resource), "ID3D11DeviceContext::Map")) { return false; } auto height = std::min(outFrame->height, (int)desc.Height); auto width = outFrame->width; auto srcLinesize = resource.RowPitch; auto dstLinesize = outFrame->linesize[0]; auto srcData = (uint8_t*)resource.pData; auto dstData = outFrame->data[0]; auto titleHeight = std::max(int(desc.Height - height), 0); auto copyLine = std::min(std::min(width * 4, (int)srcLinesize), dstLinesize); auto border = (desc.Width - width) / 2; __mtx.lock(); for (int row = 0; row < height; ++row) { auto offset = (titleHeight + row - border) * srcLinesize + border * 4; memcpy(dstData + row * dstLinesize, srcData + offset, copyLine); } __mtx.unlock(); ctx->Unmap(buffers.GetMap(), 0); if (!buffers.Reset()) { return false; } return true; }