基于Microsoft Visual Studio2019环境编写ffmpeg视频解码代码

旧代码

  • 旧代码使用了很多过时的API,这些API使用后,vs会报编译器警告 (级别 3) C4996的错误
  • 即 函数被声明为已否决 报 C4996的错误
// test_ffmpeg.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#define SDL_MAIN_HANDLED
#define __STDC_CONSTANT_MACROS
#pragma warning(disable: 4996)#include <iostream>
#include <SDL2/SDL.h>extern "C" {
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libswscale/swscale.h"
}int main(int argc,char* argv[])
{AVFormatContext *pFormatCtx;int i, videoindex;AVCodecContext* pCodeCtx;AVCodec* pCodec;AVFrame* pFrame, *pFrameYUV;uint8_t* out_buffer;AVPacket* packet;//int y_size;int ret, got_picture;struct SwsContext* img_convert_ctx;//输入文件的路径char filepath[] = "Titanic.ts";int frame_cnt;avformat_network_init();pFormatCtx = avformat_alloc_context();if (avformat_open_input(&pFormatCtx, filepath, NULL, NULL) != 0) {std::cout << "Couldn't open input stream." << std::endl;return -1;}if (avformat_find_stream_info(pFormatCtx, NULL) < 0) {std::cout << "Couldn't find stream information." << std::endl;return -1;}videoindex = -1;for (i = 0;i < pFormatCtx->nb_streams;i++) {if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {videoindex = i;break;}}if (videoindex == -1) {std::cout << "Didn't find a video stream." << std::endl;return -1;}pCodeCtx = pFormatCtx->streams[videoindex]->codec;pCodec = avcodec_find_decoder(pCodeCtx->codec_id);if (pCodec == NULL) {std::cout << "Codec not find!" << std::endl;return -1;}if (avcodec_open2(pCodeCtx, pCodec, NULL) < 0) {std::cout << "Could not open codec!" << std::endl;return -1;}/*此处添加输出视频信息的代码取自于pFormatCtx,使用std::cout输出*/pFrame = av_frame_alloc();pFrameYUV = av_frame_alloc();out_buffer = (uint8_t*)av_malloc(avpicture_get_size(AV_PIX_FMT_YUV420P, pCodeCtx->width, pCodeCtx->height));avpicture_fill((AVPicture*)pFrameYUV, out_buffer, AV_PIX_FMT_YUV420P, pCodeCtx->width, pCodeCtx->height);packet = (AVPacket*)av_malloc(sizeof(AVPacket));//Output Infostd::cout << "--------------------File Information--------------------" << std::endl;av_dump_format(pFormatCtx, 0, filepath, 0);std::cout << "--------------------------------------------------------" << std::endl;img_convert_ctx = sws_getContext(pCodeCtx->width, pCodeCtx->height, pCodeCtx->sw_pix_fmt,pCodeCtx->width, pCodeCtx->height, AV_PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL);frame_cnt = 0;while (av_read_frame(pFormatCtx,packet)>=0){if (packet->stream_index == videoindex) {/*在此处添加输出H264码流的代码取自于packet,使用fwrite()输出*/ret = avcodec_decode_video2(pCodeCtx, pFrame, &got_picture, packet);if (ret < 0) {std::cout << "Decode Frror!" << std::endl;return -1;}if (got_picture) {sws_scale(img_convert_ctx, (const uint8_t* const*)pFrame->data, pFrame->linesize, 0, pCodeCtx->height,pFrameYUV->data, pFrameYUV->linesize);std::cout << "Decoded frame index"<< frame_cnt << std::endl;/*在此处添加输出H264码流的代码取自于packet,使用fwrite()输出*/frame_cnt++;}}av_free_packet(packet);}sws_freeContext(img_convert_ctx);av_frame_free(&pFrameYUV);av_frame_free(&pFrame);avcodec_close(pCodeCtx);avformat_close_input(&pFormatCtx);return 0;
}// 运行程序: Ctrl + F5 或调试 >“开始执行(不调试)”菜单
// 调试程序: F5 或调试 >“开始调试”菜单// 入门使用技巧: 
//   1. 使用解决方案资源管理器窗口添加/管理文件
//   2. 使用团队资源管理器窗口连接到源代码管理
//   3. 使用输出窗口查看生成输出和其他消息
//   4. 使用错误列表窗口查看错误
//   5. 转到“项目”>“添加新项”以创建新的代码文件,或转到“项目”>“添加现有项”以将现有代码文件添加到项目
//   6. 将来,若要再次打开此项目,请转到“文件”>“打开”>“项目”并选择 .sln 文件
  • 编译器警告 (级别 3) C4996 | Microsoft Docs
  • 在代码头部添加#pragma warning(disable: 4996) 即可屏蔽这个错误
  • windows API 函数被声明为已否决_或许可能028的博客-CSDN博客
  • 但是 代码启动之后,因为存在隐患,仍然存在问题

  •  Assertion desc failed at C:\Users\32157\vcpkg\buildtrees\ffmpeg\src\n4.4.1-070f385ab7.clean\libswscale\swscale_internal.h:677
  • c++ - Assertion desc failed at src/libswscale/swscale_internal.h:668 - Stack Overflow
  • 错误原因:在FFmpeg该断言的最新版本中,说明outCodecContext->pix_fmt设置不正确。并且也avpicture_fill已弃用,请av_image_fill_arrays改用。
  • 因此 需要使用新版的API对旧版API进行更新迭代
  • 去除 #pragma warning(disable: 4996) 
  • 显示过时的API如下

对应修改

  • FFmpeg 被声明为已否决 deprecated_Louis_815的博客-CSDN博客
  • api函数替换,在里面搜索ctrl+F,会有英文说明的
  • PIX_FMT_YUV420P -> AV_PIX_FMT_YUV420P
  • 'AVStream::codec': 被声明为已否决:
    • if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO){
    • =>
    • if(pFormatCtx->streams[i]->codecpar->codec_type==AVMEDIA_TYPE_VIDEO){
  • 'AVStream::codec': 被声明为已否决:
    • pCodecCtx = pFormatCtx->streams[videoindex]->codec;
    • =>
    • pCodecCtx = avcodec_alloc_context3(NULL);
    • avcodec_parameters_to_context(pCodecCtx, pFormatCtx->streams[videoindex]->codecpar);
  • 'avpicture_get_size': 被声明为已否决:
    • avpicture_get_size(AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height)
    • =>
    • #include "libavutil/imgutils.h"
    • av_image_get_buffer_size(AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height, 1)
  • 'avpicture_fill': 被声明为已否决:
    • avpicture_fill((AVPicture *)pFrameYUV, out_buffer, AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height);
    • =>
    • av_image_fill_arrays(pFrameYUV->data, pFrameYUV->linesize, out_buffer, AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height, 1);
  • 'avcodec_decode_video2': 被声明为已否决:
    • ret = avcodec_decode_video2(pCodecCtx, pFrame, &got_picture, packet); //got_picture_ptr Zero if no frame could be decompressed
    • =>
    • ret = avcodec_send_packet(pCodecCtx, packet);
    • got_picture = avcodec_receive_frame(pCodecCtx, pFrame); //got_picture = 0 success, a frame was returned
    • //注意:got_picture含义相反
    • 或者:
    • int ret = avcodec_send_packet(aCodecCtx, &pkt);
    • if (ret != 0)
    • {
    • prinitf("%s/n","error");
    • return;
    • }
    • while( avcodec_receive_frame(aCodecCtx, &frame) == 0){
    • //读取到一帧音频或者视频
    • //处理解码后音视频 frame
    • }
  • 'av_free_packet': 被声明为已否决:
    • av_free_packet(packet);
    • =>
    • av_packet_unref(packet);
  • 本文代码 未涉及
  • avcodec_decode_audio4:被声明为已否决:
    • int ret = avcodec_send_packet(aCodecCtx, &pkt);
    • if (ret != 0){prinitf("%s/n","error");}
    • while( avcodec_receive_frame(aCodecCtx, &frame) == 0){
    • //读取到一帧音频或者视频
    • //处理解码后音视频 frame
    • }

修改后的代码

// test_ffmpeg.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#define SDL_MAIN_HANDLED
#define __STDC_CONSTANT_MACROS
#pragma warning(disable: 4819)#include <iostream>
#include <SDL2/SDL.h>extern "C" {
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libswscale/swscale.h"
#include "libavutil/imgutils.h"
}int main(int argc,char* argv[])
{AVFormatContext *pFormatCtx;int i, videoindex;AVCodecContext* pCodeCtx;AVCodec* pCodec;AVFrame* pFrame, *pFrameYUV;uint8_t* out_buffer;AVPacket* packet;//int y_size;int ret, got_picture;struct SwsContext* img_convert_ctx;//输入文件的路径char filepath[] = "Titanic.ts";int frame_cnt;avformat_network_init();pFormatCtx = avformat_alloc_context();if (avformat_open_input(&pFormatCtx, filepath, NULL, NULL) != 0) {std::cout << "Couldn't open input stream." << std::endl;return -1;}if (avformat_find_stream_info(pFormatCtx, NULL) < 0) {std::cout << "Couldn't find stream information." << std::endl;return -1;}videoindex = -1;for (i = 0;i < pFormatCtx->nb_streams;i++) {if (pFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {videoindex = i;break;}}if (videoindex == -1) {std::cout << "Didn't find a video stream." << std::endl;return -1;}pCodeCtx = avcodec_alloc_context3(NULL);avcodec_parameters_to_context(pCodeCtx, pFormatCtx->streams[videoindex]->codecpar);pCodec = avcodec_find_decoder(pCodeCtx->codec_id);if (pCodec == NULL) {std::cout << "Codec not find!" << std::endl;return -1;}if (avcodec_open2(pCodeCtx, pCodec, NULL) < 0) {std::cout << "Could not open codec!" << std::endl;return -1;}/*此处添加输出视频信息的代码取自于pFormatCtx,使用std::cout输出*/pFrame = av_frame_alloc();pFrameYUV = av_frame_alloc();out_buffer = (uint8_t*)av_malloc(av_image_get_buffer_size(AV_PIX_FMT_YUV420P, pCodeCtx->width, pCodeCtx->height,1));av_image_fill_arrays(pFrameYUV->data,pFrameYUV->linesize,out_buffer,AV_PIX_FMT_YUV420P,pCodeCtx->width,pCodeCtx->height,1);packet = (AVPacket*)av_malloc(sizeof(AVPacket));//Output Infostd::cout << "--------------------File Information--------------------" << std::endl;av_dump_format(pFormatCtx, 0, filepath, 0);std::cout << "--------------------------------------------------------" << std::endl;img_convert_ctx = sws_getContext(pCodeCtx->width, pCodeCtx->height, pCodeCtx->sw_pix_fmt,pCodeCtx->width, pCodeCtx->height, AV_PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL);frame_cnt = 0;while (av_read_frame(pFormatCtx,packet)>=0){if (packet->stream_index == videoindex) {/*在此处添加输出H264码流的代码取自于packet,使用fwrite()输出*/ret = avcodec_send_packet(pCodeCtx, packet);//注意 got_picture=0 success,a frame was returned got_picture = avcodec_receive_frame(pCodeCtx, pFrame);if (ret < 0) {std::cout << "Decode Frror!" << std::endl;return -1;}if (got_picture) {sws_scale(img_convert_ctx, (const uint8_t* const*)pFrame->data, pFrame->linesize, 0, pCodeCtx->height,pFrameYUV->data, pFrameYUV->linesize);std::cout << "Decoded frame index"<< frame_cnt << std::endl;/*在此处添加输出H264码流的代码取自于packet,使用fwrite()输出*/frame_cnt++;}}av_packet_unref(packet);}sws_freeContext(img_convert_ctx);av_frame_free(&pFrameYUV);av_frame_free(&pFrame);avcodec_close(pCodeCtx);avformat_close_input(&pFormatCtx);return 0;
}// 运行程序: Ctrl + F5 或调试 >“开始执行(不调试)”菜单
// 调试程序: F5 或调试 >“开始调试”菜单// 入门使用技巧: 
//   1. 使用解决方案资源管理器窗口添加/管理文件
//   2. 使用团队资源管理器窗口连接到源代码管理
//   3. 使用输出窗口查看生成输出和其他消息
//   4. 使用错误列表窗口查看错误
//   5. 转到“项目”>“添加新项”以创建新的代码文件,或转到“项目”>“添加现有项”以将现有代码文件添加到项目
//   6. 将来,若要再次打开此项目,请转到“文件”>“打开”>“项目”并选择 .sln 文件

 问题仍未解决

  •  还是同一个错误
  •  Assertion desc failed at C:\Users\32157\vcpkg\buildtrees\ffmpeg\src\n4.4.1-070f385ab7.clean\libswscale\swscale_internal.h:677

再次修改代码

  • 在代码头部添加#pragma warning(disable: 4996) 即可屏蔽这个错误
  • 用FFmpeg实现Mp4,mkv等格式的解码。解码为h264和YUV数据并存在文件中
  • 参考链接:ffmpeg实战教程(一)Mp4,mkv等格式解码为h264和yuv数据_Louis_815的博客-CSDN博客
// test_ffmpeg.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
///*
#define SDL_MAIN_HANDLED
#define __STDC_CONSTANT_MACROS
#pragma warning(disable: 4819)#include <iostream>
#include <SDL2/SDL.h>extern "C" {
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libswscale/swscale.h"
#include "libavutil/imgutils.h"
}
*/#pragma warning(disable: 4996)#include <stdio.h>#define __STDC_CONSTANT_MACROS#ifdef _WIN32
//Windows
extern "C"
{
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libswscale/swscale.h"
};
#else
//Linux...
#ifdef __cplusplus
extern "C"
{
#endif
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
#ifdef __cplusplus
};
#endif
#endifint main(int argc, char* argv[])
{AVFormatContext* pFormatCtx;int             i, videoindex;AVCodecContext* pCodecCtx;AVCodec* pCodec;AVFrame* pFrame, * pFrameYUV;uint8_t* out_buffer;AVPacket* packet;int y_size;int ret, got_picture;struct SwsContext* img_convert_ctx;char filepath[] = "Forrest_Gump_IMAX.mp4";FILE* fp_yuv = fopen("output.yuv", "wb+");FILE* fp_h264 = fopen("output.h264", "wb+");av_register_all();//注册所有组件avformat_network_init();//初始化网络pFormatCtx = avformat_alloc_context();//初始化一个AVFormatContextif (avformat_open_input(&pFormatCtx, filepath, NULL, NULL) != 0) {//打开输入的视频文件printf("Couldn't open input stream.\n");return -1;}if (avformat_find_stream_info(pFormatCtx, NULL) < 0) {//获取视频文件信息printf("Couldn't find stream information.\n");return -1;}videoindex = -1;for (i = 0; i < pFormatCtx->nb_streams; i++)if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {videoindex = i;break;}if (videoindex == -1) {printf("Didn't find a video stream.\n");return -1;}pCodecCtx = pFormatCtx->streams[videoindex]->codec;pCodec = avcodec_find_decoder(pCodecCtx->codec_id);//查找解码器if (pCodec == NULL) {printf("Codec not found.\n");return -1;}if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0) {//打开解码器printf("Could not open codec.\n");return -1;}pFrame = av_frame_alloc();pFrameYUV = av_frame_alloc();out_buffer = (uint8_t*)av_malloc(avpicture_get_size(AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height));avpicture_fill((AVPicture*)pFrameYUV, out_buffer, AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height);packet = (AVPacket*)av_malloc(sizeof(AVPacket));//Output Info-----------------------------printf("--------------- File Information ----------------\n");av_dump_format(pFormatCtx, 0, filepath, 0);printf("-------------------------------------------------\n");img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt,pCodecCtx->width, pCodecCtx->height, AV_PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL);while (av_read_frame(pFormatCtx, packet) >= 0) {//读取一帧压缩数据if (packet->stream_index == videoindex) {fwrite(packet->data, 1, packet->size, fp_h264); //把H264数据写入fp_h264文件ret = avcodec_decode_video2(pCodecCtx, pFrame, &got_picture, packet);//解码一帧压缩数据if (ret < 0) {printf("Decode Error.\n");return -1;}if (got_picture) {sws_scale(img_convert_ctx, (const uint8_t* const*)pFrame->data, pFrame->linesize, 0, pCodecCtx->height,pFrameYUV->data, pFrameYUV->linesize);y_size = pCodecCtx->width * pCodecCtx->height;fwrite(pFrameYUV->data[0], 1, y_size, fp_yuv);    //Y fwrite(pFrameYUV->data[1], 1, y_size / 4, fp_yuv);  //Ufwrite(pFrameYUV->data[2], 1, y_size / 4, fp_yuv);  //Vprintf("Succeed to decode 1 frame!\n");}}av_free_packet(packet);}//flush decoder/*当av_read_frame()循环退出的时候,实际上解码器中可能还包含剩余的几帧数据。因此需要通过“flush_decoder”将这几帧数据输出。“flush_decoder”功能简而言之即直接调用avcodec_decode_video2()获得AVFrame,而不再向解码器传递AVPacket。*/while (1) {ret = avcodec_decode_video2(pCodecCtx, pFrame, &got_picture, packet);if (ret < 0)break;if (!got_picture)break;sws_scale(img_convert_ctx, (const uint8_t* const*)pFrame->data, pFrame->linesize, 0, pCodecCtx->height,pFrameYUV->data, pFrameYUV->linesize);int y_size = pCodecCtx->width * pCodecCtx->height;fwrite(pFrameYUV->data[0], 1, y_size, fp_yuv);    //Y fwrite(pFrameYUV->data[1], 1, y_size / 4, fp_yuv);  //Ufwrite(pFrameYUV->data[2], 1, y_size / 4, fp_yuv);  //Vprintf("Flush Decoder: Succeed to decode 1 frame!\n");}sws_freeContext(img_convert_ctx);//关闭文件以及释放内存fclose(fp_yuv);fclose(fp_h264);av_frame_free(&pFrameYUV);av_frame_free(&pFrame);avcodec_close(pCodecCtx);avformat_close_input(&pFormatCtx);return 0;
}// 运行程序: Ctrl + F5 或调试 >“开始执行(不调试)”菜单
// 调试程序: F5 或调试 >“开始调试”菜单// 入门使用技巧: 
//   1. 使用解决方案资源管理器窗口添加/管理文件
//   2. 使用团队资源管理器窗口连接到源代码管理
//   3. 使用输出窗口查看生成输出和其他消息
//   4. 使用错误列表窗口查看错误
//   5. 转到“项目”>“添加新项”以创建新的代码文件,或转到“项目”>“添加现有项”以将现有代码文件添加到项目
//   6. 将来,若要再次打开此项目,请转到“文件”>“打开”>“项目”并选择 .sln 文件

 最后修改代码

  • fopen 和 fopen_s 之间的差异
    • fopen和fopen_s用法的比较_xingcen的博客-CSDN博客_c++ fopen_s
    • fopen_s、_wfopen_s | Microsoft Docs
  • avcodec_send_packet 和 avcodec_receive_frame 替代 avcodec_decode_video2
    • ffmpeg 新版本avcodec_send_packet 和avcodec_receive_frame实现解码_Lammyzp的博客-CSDN博客_avcodec_send_packet
    • FFmpeg: decode_video.c
    • FFmpeg: Decoding
    • FFMPEG开发快速入坑——音视频解码处理 - 知乎
// test_ffmpeg.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
//#pragma warning(disable: 4996)#include <stdio.h>#define __STDC_CONSTANT_MACROS#ifdef _WIN32
//Windows
extern "C"
{
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libswscale/swscale.h"
#include "libavutil/imgutils.h"
};
#else
//Linux...
#ifdef __cplusplus
extern "C"
{
#endif
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
#ifdef __cplusplus
};
#endif
#include <cerrno>
#endifint main(int argc, char* argv[])
{AVFormatContext* pFormatCtx;int             i, videoindex;AVCodecContext* pCodecCtx;AVCodec* pCodec;AVFrame* pFrame, * pFrameYUV;uint8_t* out_buffer;AVPacket* packet;int y_size;int ret, got_picture;struct SwsContext* img_convert_ctx;char filepath[] = "Forrest_Gump_IMAX.mp4";//FILE* fp_yuv = fopen("output.yuv", "wb+");errno_t err;FILE* fp_yuv = NULL;if ((err = fopen_s(&fp_yuv, "output.yuv", "wb+")) != 0) {printf("Couldn't open fp_yuv.\n");}//FILE* fp_h264 = fopen("output.h264", "wb+");FILE* fp_h264 = NULL;if ((err = fopen_s(&fp_h264, "output.h264", "wb+")) != 0) {printf("Couldn't open fp_h264.\n");}//av_register_all();//注册所有组件avformat_network_init();//初始化网络pFormatCtx = avformat_alloc_context();//初始化一个AVFormatContextif (avformat_open_input(&pFormatCtx, filepath, NULL, NULL) != 0) {//打开输入的视频文件printf("Couldn't open input stream.\n");return -1;}if (avformat_find_stream_info(pFormatCtx, NULL) < 0) {//获取视频文件信息printf("Couldn't find stream information.\n");return -1;}videoindex = -1;for (i = 0; i < pFormatCtx->nb_streams; i++)if (pFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {videoindex = i;break;}if (videoindex == -1) {printf("Didn't find a video stream.\n");return -1;}//pCodecCtx = pFormatCtx->streams[videoindex]->codec;pCodecCtx = avcodec_alloc_context3(NULL);avcodec_parameters_to_context(pCodecCtx, pFormatCtx->streams[videoindex]->codecpar);pCodec = avcodec_find_decoder(pCodecCtx->codec_id);//查找解码器if (pCodec == NULL) {printf("Codec not found.\n");return -1;}if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0) {//打开解码器printf("Could not open codec.\n");return -1;}pFrame = av_frame_alloc();pFrameYUV = av_frame_alloc();out_buffer = (uint8_t*)av_malloc(av_image_get_buffer_size(AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height,1));//avpicture_fill((AVPicture*)pFrameYUV, out_buffer, AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height);av_image_fill_arrays(pFrameYUV->data, pFrameYUV->linesize, out_buffer, AV_PIX_FMT_YUV420P,pCodecCtx->width, pCodecCtx->height, 1);packet = (AVPacket*)av_malloc(sizeof(AVPacket));//Output Info-----------------------------printf("--------------- File Information ----------------\n");av_dump_format(pFormatCtx, 0, filepath, 0);printf("-------------------------------------------------\n");img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt,pCodecCtx->width, pCodecCtx->height, AV_PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL);while (av_read_frame(pFormatCtx, packet) >= 0) {//读取一帧压缩数据if (packet->stream_index == videoindex) {fwrite(packet->data, 1, packet->size, fp_h264); //把H264数据写入fp_h264文件//ret = avcodec_decode_video2(pCodecCtx, pFrame, &got_picture, packet);//解码一帧压缩数据ret = avcodec_send_packet(pCodecCtx, packet);if (ret < 0) {printf("Error sending a packet for decoding.\n");return -1;}//while (ret >= 0) {got_picture = avcodec_receive_frame(pCodecCtx, pFrame);//缺失错误处理和检测if (got_picture==0) {sws_scale(img_convert_ctx, (const uint8_t* const*)pFrame->data, pFrame->linesize, 0, pCodecCtx->height,pFrameYUV->data, pFrameYUV->linesize);y_size = pCodecCtx->width * pCodecCtx->height;fwrite(pFrameYUV->data[0], 1, y_size, fp_yuv);    //Y fwrite(pFrameYUV->data[1], 1, y_size / 4, fp_yuv);  //Ufwrite(pFrameYUV->data[2], 1, y_size / 4, fp_yuv);  //Vprintf("Succeed to decode 1 frame!\n");}//}}//av_free_packet(packet);av_packet_unref(packet);}//flush decoder/*当av_read_frame()循环退出的时候,实际上解码器中可能还包含剩余的几帧数据。因此需要通过“flush_decoder”将这几帧数据输出。“flush_decoder”功能简而言之即直接调用avcodec_decode_video2()获得AVFrame,而不再向解码器传递AVPacket。*/while (1) {//ret = avcodec_decode_video2(pCodecCtx, pFrame, &got_picture, packet);ret = avcodec_send_packet(pCodecCtx, packet);if (ret < 0)break;got_picture = avcodec_receive_frame(pCodecCtx, pFrame);if (got_picture!=0)break;sws_scale(img_convert_ctx, (const uint8_t* const*)pFrame->data, pFrame->linesize, 0, pCodecCtx->height,pFrameYUV->data, pFrameYUV->linesize);int y_size = pCodecCtx->width * pCodecCtx->height;fwrite(pFrameYUV->data[0], 1, y_size, fp_yuv);    //Y fwrite(pFrameYUV->data[1], 1, y_size / 4, fp_yuv);  //Ufwrite(pFrameYUV->data[2], 1, y_size / 4, fp_yuv);  //Vprintf("Flush Decoder: Succeed to decode 1 frame!\n");}sws_freeContext(img_convert_ctx);//关闭文件以及释放内存fclose(fp_yuv);fclose(fp_h264);av_frame_free(&pFrameYUV);av_frame_free(&pFrame);avcodec_close(pCodecCtx);avformat_close_input(&pFormatCtx);return 0;
}// 运行程序: Ctrl + F5 或调试 >“开始执行(不调试)”菜单
// 调试程序: F5 或调试 >“开始调试”菜单// 入门使用技巧: 
//   1. 使用解决方案资源管理器窗口添加/管理文件
//   2. 使用团队资源管理器窗口连接到源代码管理
//   3. 使用输出窗口查看生成输出和其他消息
//   4. 使用错误列表窗口查看错误
//   5. 转到“项目”>“添加新项”以创建新的代码文件,或转到“项目”>“添加现有项”以将现有代码文件添加到项目
//   6. 将来,若要再次打开此项目,请转到“文件”>“打开”>“项目”并选择 .sln 文件

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/446013.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

16进制转double dotnet_终于把计算机进制弄明白了!

And theres one thing that I need from you我只需要你为我做一-件事Can you come through, through待在我的身边就好Through, yeah你可以抚慰一切不满And theres one thing that I need from you你可以过来Can you come through?待在我的身边吗-comethruJeremy Zucker进制进制…

FFmpeg源代码简单分析-架构图-解码

参考链接 FFmpeg源代码结构图 - 解码_雷霄骅的博客-CSDN博客_ffmpeg雷霄骅函数背景色 函数在图中以方框的形式表现出来。不同的背景色标志了该函数不同的作用&#xff1a; 粉红色背景函数&#xff1a;FFmpeg的API函数。白色背景的函数&#xff1a;FFmpeg的内部函数。黄色背景…

JUnit单元测试笔记

#01 JUnit简介 1.在项目工程中的Library,add 一个JUnit的Jar包&#xff0c;按需要添加JUnit 3 或 JUnit 4&#xff08;分为被测试类与测试类较佳&#xff09;。 2.单元测试是由程序员完成的。 3.Java 5 之前的版本只能 用JUnit 4前的版本&#xff08;因为JUnit 4用到Java 5的…

jqery获取每个月天数_三年级《年、月、日》单元重要知识点整理汇总,以及难点题型解析...

昨天给大家分享了《计算经过的时间》问题&#xff0c;今天给大家分享的是《年、月、日》单元中重要的几个知识点&#xff0c;以及难点题型解析。知识点1 感知年、月、日一、结合生活实际&#xff0c;看看下面事情需要经过多少时间。跑完100米大约需要经过十几(秒)。2.打一场篮球…

FFmpeg源代码简单分析-架构图-编码

参考链接 FFmpeg源代码结构图 - 编码_雷霄骅的博客-CSDN博客_ffmpeg 源码函数背景色 函数在图中以方框的形式表现出来。不同的背景色标志了该函数不同的作用&#xff1a; 粉红色背景函数&#xff1a;FFmpeg的API函数。白色背景的函数&#xff1a;FFmpeg的内部函数。黄色背景的…

为革命,保护视力——为Eclipse更换暗黑皮肤及编辑页面的字体颜色主题

1.在Eclipse中的菜单栏的Help -> Eclipse Market 的 Search栏中输入 Eclipse Moonrise UI Theme &#xff0c;之后自己执生啦&#xff08;确保上网配置正确&#xff09;。 2.与上面操作类似&#xff0c;输入 Eclipse Color Theme&#xff0c;选择安装。 3.选择菜单栏的Win…

FFmpeg源代码简单分析-通用- 内存的分配和释放(av_malloc()、av_free()等)

参考链接 FFmpeg源代码简单分析&#xff1a;内存的分配和释放&#xff08;av_malloc()、av_free()等&#xff09;_雷霄骅的博客-CSDN博客_av_malloc 内容介绍 内存操作的常见函数位于libavutil\mem.c中本文记录最常使用的几个函数&#xff1a; av_malloc()av_realloc()av_mal…

FFmpeg源代码简单分析-通用-结构体分析-AVFormatContext

参考链接 FFMPEG结构体分析&#xff1a;AVFormatContext_雷霄骅的博客-CSDN博客_avformatcontext AVFormatContext AVFormatContext是包含码流参数较多的结构体结构体的定义位于libavformat/avformat.h/*** Format I/O context.//格式化 I/O 上下文* New fields can be added…

plsql如何显示表结构图_【论文攻略】排版技巧——如何用 Word 编辑参考文献

每个需要写毕业论文的朋友都会发现&#xff0c;修改文献是一件非常痛苦的事情&#xff0c;虽然现在也有很多软件可以编排参考文献&#xff0c;其实 word 本身就可以。采用合适的编辑方法会方便地做到整齐,规范, 自动排序和交叉引用。 1. 以尾注的方式插入第一个参考文献将光标定…

FFmpeg源代码简单分析-通用-结构体分析-AVCodecContext

参考链接 FFMPEG结构体分析&#xff1a;AVCodecContext_雷霄骅的博客-CSDN博客_avcodeccontext AVCodecContext AVCodecContext是包含变量较多的结构体&#xff08;感觉差不多是变量最多的结构体&#xff09;结构体的定义位于avcodec.h关键的变量如下所示&#xff08;仅仅考虑…

Hello OpenGL——OpenGL在Visual c++6.0安装和配置

1、下载并安装glut库opengl的glut库 GLUT不是OpenGL所必须的&#xff0c;但它会给我们的学习带来一定的方便&#xff0c;推荐安装。 Windows环境下的GLUT下载地址&#xff1a;&#xff08;大小约为150k&#xff09; http://www.opengl.org/resources/libraries/glut/glutdlls37…

FFmpeg源代码简单分析-通用-结构体分析-AVIOContext

参考链接 FFMPEG结构体分析&#xff1a;AVIOContext_雷霄骅的博客-CSDN博客_aviocontext AVIOContext AVIOContext是FFMPEG管理输入输出数据的结构体结构体的定义位于位于avio.h关键的变量如下所示 unsigned char *buffer&#xff1a;缓存开始位置int buffer_size&#xff1…

初闻动态规划

前言 本文以一道常见的算法面试题开篇&#xff0c;引入动态规划的基础概念&#xff0c; 介绍其思考过程。 正文 一、常见的一道算法面试题——上台阶 有一个楼梯总共n个台阶&#xff0c;只能往上走&#xff0c;每次只能上1个、2个台阶&#xff0c;总共有多少种走法。 解决…

FFmpeg源代码简单分析-通用-结构体分析-AVCodec

参考链接 FFMPEG结构体分析&#xff1a;AVCodec_雷霄骅的博客-CSDN博客_avcodec AVCodec AVCodec是存储编解码器信息的结构体结构体的定义位于avcodec.h文件中最主要的几个变量 const char *name&#xff1a;编解码器的名字&#xff0c;比较短const char *long_name&#xff…

SLF4J简介与使用(整合log4j)

SLF4J简介与使用(整合log4j) 一、概念 SLF4J的全称是Simple Logging Facade for Java&#xff0c;即简单日志门面。SLF4J并不是具体的日志框架&#xff0c;而是作为一个简单门面服务于各类日志框架&#xff0c;如java.util.logging, logback和log4j。 SLF4J提供了统一的记录…

multism中ui和uo应该怎么表示_王者荣耀:梦泪直播时谈到体验服大改动,表示装备的改动很关键...

王者荣耀的主播梦泪&#xff0c;大家都很熟了&#xff0c;也是一个很强的主播&#xff0c;他对于王者荣耀的理解&#xff0c;还是非常深刻的&#xff0c;而最近王者荣耀的体验服&#xff0c;进行了大改动&#xff0c;也是改变了很多的东西。对此&#xff0c;网友们也是非常的在…

怎么关闭或者卸载ivanti_电脑软件卸载不了怎么办,教您解决电脑软件无法卸载方法技巧...

我们在使用电脑的过程中&#xff0c;肯定会安装各种软件&#xff0c;但是一些软件在使用完之后就不会再使用了&#xff0c;但又无法卸载。下面由小编分享一下电脑安装的软件无法卸载解决方法&#xff0c;如果你在某卸载软件的时候出现无法卸载的情况&#xff0c;不妨通过以下方…

解决Github图片加载失败

问题描述 浏览自己Github某仓库的README.md内时&#xff0c;发现文档的图片始终加载不出&#xff0c;打开浏览器后台&#xff0c;冒出一片红&#xff0c;Failed to load resource: net::ERR_CONNECTION_RESET&#xff0c;如下图所示&#xff1a; 问题分析 可能造成这问题的原…

FFmpeg源代码简单分析-通用-结构体分析-关键结构体之间的关系

参考链接 FFMPEG中最关键的结构体之间的关系_雷霄骅的博客-CSDN博客_ffmpeg 结构体关系 最关键的结构体可以分成以下几类&#xff1a; 解协议&#xff08;http,rtsp,rtmp,mms&#xff09; AVIOContext&#xff0c;URLProtocol&#xff0c;URLContext主要存储视音频使用的协…

用Python下载文件

前提条件 需要事先安装requests模块&#xff1a; pip install requests 放码过来 import requestsurl XXX #文件下载来源URL filename #下载到本地后新文件名 r requests.get(url) with open(filename, "wb") as code:code.write(r.content)实战演习 从目标…