无法将 ffmpeg 中的 YUV 帧写入 .yuv 文件
Can't write YUV Frame from ffmpeg into .yuv file
我的目标是将我解码的帧写入文件。我知道我捕捉得很好,因为它显示在我的 SDL 回放中,然后我对其进行编码,没有任何问题。然而,我似乎无法将框架正确写入文件。这是代码:
#define PIXFMT AV_PIX_FMT_YUV420P
#define WIDTH 1280
#define HEIGHT 720
// initialize SWS context for software scaling
sws_ctx = sws_getContext(pCodecCtx->width,
pCodecCtx->height,
pCodecCtx->pix_fmt,
WIDTH,
HEIGHT,
PIXFMT,
SWS_LANCZOS,
NULL,
NULL,
NULL
);
FfmpegEncoder enc("rtsp://127.0.0.1:1935/live/myStream", pParser);
//SetPixelArray();
i = 0;
enc.FillYuvImage(pFrameRGB, 0, this->pCodecCtx->width, this->pCodecCtx->height);
FILE *pFile;
while (av_read_frame(pFormatCtx, &packet) >= 0 && !exit) {
if (packet.stream_index == videoindex) {
// Decode video frame
avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packet);
if (frameFinished) {
i++;
sws_scale(sws_ctx, (uint8_t const * const *)pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameRGB->data, pFrameRGB->linesize);
if (i < 500)
{
pFile = fopen(std::string("./screenshots/screen.yuv").c_str(), "a+");
for (int y = 0; y < pCodecCtx->height; y++)
{
fwrite(pFrame->data[0] + y * pFrame->linesize[0], 1, pCodecCtx->width * pCodecCtx->height, pFile);
fwrite(pFrame->data[1] + y * pFrame->linesize[1], 1, pCodecCtx->width * pCodecCtx->height / 4, pFile);
fwrite(pFrame->data[2] + y * pFrame->linesize[2], 1, pCodecCtx->width * pCodecCtx->height / 4, pFile);
}
fclose(pFile);
}
enc.encodeFrame(pFrameRGB);
}
}
// Free the packet that was allocated by av_read_frame
av_free_packet(&packet);
}
程序在尝试写入框架时崩溃。
正如我在评论中提到的,您需要检查 fopen 是否成功。
但我认为问题是您编写的内容多于缓冲区中存在的内容。我对yuv的了解有限。我认为您应该执行以下操作。这是我根据Single Frame YUV420图片在this page.
中的理解
abcfor (int y = 0; y < pCodecCtx->height; y++) //plane 0: same width and height
{
fwrite(pFrame->data[0] + y * pFrame->linesize[0], 1, pCodecCtx->width, pFile);
}
for (int y = 0; y < pCodecCtx->height/4; y++) //plane1: Same width and quarter height.
{
fwrite(pFrame->data[1] + y * pFrame->linesize[1], 1, pCodecCtx->width, pFile);
}
for (int y = 0; y < pCodecCtx->height/4; y++) //plane2: Same width and quarter height.
{
fwrite(pFrame->data[2] + y * pFrame->linesize[2], 1, pCodecCtx->width, pFile);
}
请注意,书写顺序取决于颜色格式。我希望您关注每次迭代中 fwrite()
中的循环迭代次数和字节数。
首先,感谢您的所有评论和回答!
这是固定代码:
while (av_read_frame(pFormatCtx, &packet) >= 0 && !exit && i < 1000) {
if (packet.stream_index == videoindex) {
// Decode video frame
avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packet);
if (frameFinished) {
i++;
sws_scale(sws_ctx, (uint8_t const * const *)pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameRGB->data, pFrameRGB->linesize);
if ((pFile = fopen(std::string("./screenshots/screen.yuv").c_str(), "ab")) == NULL)
continue;
fwrite(pFrameRGB->data[0], 1, pCodecCtx->width * pCodecCtx->height, pFile);
fwrite(pFrameRGB->data[1], 1, pCodecCtx->width * pCodecCtx->height / 4, pFile);
fwrite(pFrameRGB->data[2], 1, pCodecCtx->width * pCodecCtx->height / 4, pFile);
fclose(pFile);
enc.encodeFrame(pFrameRGB);
}
}
// Free the packet that was allocated by av_read_frame
av_free_packet(&packet);
}
我之前用错了框架,还有错误的数据和大小。
我的目标是将我解码的帧写入文件。我知道我捕捉得很好,因为它显示在我的 SDL 回放中,然后我对其进行编码,没有任何问题。然而,我似乎无法将框架正确写入文件。这是代码:
#define PIXFMT AV_PIX_FMT_YUV420P
#define WIDTH 1280
#define HEIGHT 720
// initialize SWS context for software scaling
sws_ctx = sws_getContext(pCodecCtx->width,
pCodecCtx->height,
pCodecCtx->pix_fmt,
WIDTH,
HEIGHT,
PIXFMT,
SWS_LANCZOS,
NULL,
NULL,
NULL
);
FfmpegEncoder enc("rtsp://127.0.0.1:1935/live/myStream", pParser);
//SetPixelArray();
i = 0;
enc.FillYuvImage(pFrameRGB, 0, this->pCodecCtx->width, this->pCodecCtx->height);
FILE *pFile;
while (av_read_frame(pFormatCtx, &packet) >= 0 && !exit) {
if (packet.stream_index == videoindex) {
// Decode video frame
avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packet);
if (frameFinished) {
i++;
sws_scale(sws_ctx, (uint8_t const * const *)pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameRGB->data, pFrameRGB->linesize);
if (i < 500)
{
pFile = fopen(std::string("./screenshots/screen.yuv").c_str(), "a+");
for (int y = 0; y < pCodecCtx->height; y++)
{
fwrite(pFrame->data[0] + y * pFrame->linesize[0], 1, pCodecCtx->width * pCodecCtx->height, pFile);
fwrite(pFrame->data[1] + y * pFrame->linesize[1], 1, pCodecCtx->width * pCodecCtx->height / 4, pFile);
fwrite(pFrame->data[2] + y * pFrame->linesize[2], 1, pCodecCtx->width * pCodecCtx->height / 4, pFile);
}
fclose(pFile);
}
enc.encodeFrame(pFrameRGB);
}
}
// Free the packet that was allocated by av_read_frame
av_free_packet(&packet);
}
程序在尝试写入框架时崩溃。
正如我在评论中提到的,您需要检查 fopen 是否成功。
但我认为问题是您编写的内容多于缓冲区中存在的内容。我对yuv的了解有限。我认为您应该执行以下操作。这是我根据Single Frame YUV420图片在this page.
中的理解abcfor (int y = 0; y < pCodecCtx->height; y++) //plane 0: same width and height
{
fwrite(pFrame->data[0] + y * pFrame->linesize[0], 1, pCodecCtx->width, pFile);
}
for (int y = 0; y < pCodecCtx->height/4; y++) //plane1: Same width and quarter height.
{
fwrite(pFrame->data[1] + y * pFrame->linesize[1], 1, pCodecCtx->width, pFile);
}
for (int y = 0; y < pCodecCtx->height/4; y++) //plane2: Same width and quarter height.
{
fwrite(pFrame->data[2] + y * pFrame->linesize[2], 1, pCodecCtx->width, pFile);
}
请注意,书写顺序取决于颜色格式。我希望您关注每次迭代中 fwrite()
中的循环迭代次数和字节数。
首先,感谢您的所有评论和回答! 这是固定代码:
while (av_read_frame(pFormatCtx, &packet) >= 0 && !exit && i < 1000) {
if (packet.stream_index == videoindex) {
// Decode video frame
avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packet);
if (frameFinished) {
i++;
sws_scale(sws_ctx, (uint8_t const * const *)pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameRGB->data, pFrameRGB->linesize);
if ((pFile = fopen(std::string("./screenshots/screen.yuv").c_str(), "ab")) == NULL)
continue;
fwrite(pFrameRGB->data[0], 1, pCodecCtx->width * pCodecCtx->height, pFile);
fwrite(pFrameRGB->data[1], 1, pCodecCtx->width * pCodecCtx->height / 4, pFile);
fwrite(pFrameRGB->data[2], 1, pCodecCtx->width * pCodecCtx->height / 4, pFile);
fclose(pFile);
enc.encodeFrame(pFrameRGB);
}
}
// Free the packet that was allocated by av_read_frame
av_free_packet(&packet);
}
我之前用错了框架,还有错误的数据和大小。