python ffmpeg4 保存h264

举报
风吹稻花香 发表于 2021/06/05 00:54:54 2021/06/05
【摘要】 // dllmain.cpp : 定义 DLL 应用程序的入口点。 #include <windows.h>BOOL APIENTRY DllMain( HMODULE hModule,                       DWORD &...

  
  1. // dllmain.cpp : 定义 DLL 应用程序的入口点。
  2. #include <windows.h>
  3. BOOL APIENTRY DllMain( HMODULE hModule,
  4.                        DWORD  ul_reason_for_call,
  5.                        LPVOID lpReserved
  6.                      )
  7. {
  8.     switch (ul_reason_for_call)
  9.     {
  10.     case DLL_PROCESS_ATTACH:
  11.     case DLL_THREAD_ATTACH:
  12.     case DLL_THREAD_DETACH:
  13.     case DLL_PROCESS_DETACH:
  14.         break;
  15.     }
  16.     return TRUE;
  17. }
  18. MYLIBDLL void* pre_save(char* filepath, int width, int height, int frame_rate);
  19. MYLIBDLL int save_frame(int* plus1, int len, void* vp);
  20. void* pre_save(char* filepath, int width, int height, int frame_rate) {
  21.     av_log_set_level(AV_LOG_ERROR);
  22.     Rtmp_tool *rtmp_tool;
  23.     rtmp_tool = new Rtmp_tool();
  24.     int nLen;
  25.     int fileI;
  26.     rtmp_tool->nWidth = width;
  27.     rtmp_tool->nHeight = height;
  28.     av_register_all();
  29.     avcodec_register_all();   
  30.     AVCodecContext *c = NULL;
  31.     AVCodecContext *in_c = NULL;
  32.     AVCodec *pCodecH264; //编码器    
  33.     pCodecH264 = avcodec_find_encoder(AV_CODEC_ID_H264);//查找h264编码器    
  34.     c = avcodec_alloc_context3(pCodecH264);
  35.     if (!c)
  36.     {
  37.         printf("Could not allocate video codec context\n");
  38.         exit(1);
  39.     }
  40.     c->bit_rate = 1024 * 1024;// put sample parameters     
  41.     c->width = width;
  42.     c->height = height;
  43.     c->time_base.den = frame_rate;//视频每秒帧数
  44.     c->time_base.num = 1;
  45.     c->framerate.den = 1;//视频帧速
  46.     c->framerate.num = frame_rate;
  47.     c->gop_size = 20; // emit one intra frame every ten frames     
  48.     c->max_b_frames = 1;
  49.     c->thread_count = 1;
  50.     c->pix_fmt = AV_PIX_FMT_YUV420P;//PIX_FMT_RGB24; 
  51.                                     //打开编码器    
  52.     if (avcodec_open2(c, pCodecH264, NULL)<0)
  53.         printf("不能打开编码库");
  54.     int size = c->width * c->height;
  55.     rtmp_tool->yuv_buff = (uint8_t *)malloc((size * 3) / 2); // size for YUV 420     
  56.     rtmp_tool->f = fopen(filepath, "wb");
  57.     if (!rtmp_tool->f)
  58.     {
  59.         printf("could not open %s\n", filepath);
  60.         exit(1);
  61.     }
  62.     printf("context3 w h %d %d\n", c->width, c->height);
  63.     AVFrame *frame = av_frame_alloc();
  64.     if (!frame) {
  65.         fprintf(stderr, "Could not allocate video frame\n");
  66.         exit(1);
  67.     }
  68.     frame->format = c->pix_fmt;
  69.     frame->width = c->width;
  70.     frame->height = c->height;
  71.     int ret = av_frame_get_buffer(frame, 32);
  72.     if (ret < 0)
  73.     {
  74.         printf("Could not allocate the video frame data\n");
  75.         exit(1);
  76.     }
  77.     //初始化格式转换器SwsContext  
  78.     rtmp_tool->scxt = sws_getContext(c->width, c->height, AV_PIX_FMT_BGR24, c->width, c->height, AV_PIX_FMT_YUV420P, SWS_POINT, NULL, NULL, NULL);
  79.     rtmp_tool->m_pYUVFrame = frame;
  80.     rtmp_tool->c = c;
  81.     return rtmp_tool;
  82. }
  83. int save_frame(int* plus1, int len, void* vp) {
  84.     Rtmp_tool *rtmp_tool = (Rtmp_tool *)vp;
  85.     av_log_set_level(AV_LOG_DEBUG);
  86.     for (int i = 0; i < len; i++) {
  87.         plus1[i] = (uint8_t)plus1[i];
  88.     }
  89.     AVCodecContext *c = rtmp_tool->c;// (AVCodecContext*)vp;
  90.     AVPacket *avpkt;
  91.     AVFrame *m_pRGBFrame = rtmp_tool->m_pRGBFrame;
  92.     AVFrame *m_pYUVFrame = rtmp_tool->m_pYUVFrame;
  93.     /*unsigned char *pBmpBuf;
  94.     pBmpBuf = new unsigned char[len];*/
  95.     //memcpy(rgb_buff, (uint8_t*)plus1, nDataLen);
  96.     //
  97.     av_image_fill_arrays(m_pRGBFrame->data, m_pRGBFrame->linesize, (uint8_t*)plus1, AV_PIX_FMT_RGB24, rtmp_tool->nWidth, rtmp_tool->nHeight, 1);
  98.     m_pRGBFrame->width = rtmp_tool->nWidth;
  99.     m_pRGBFrame->height = rtmp_tool->nHeight;
  100.     uint8_t *p = m_pRGBFrame->data[0];
  101.     int y = 0, x = 0;
  102.     for (y = 0; y < rtmp_tool->nHeight; y++) {
  103.         for (x = 0; x < rtmp_tool->nWidth; x++) {
  104.             *p++ = (uint8_t)plus1[(y*rtmp_tool->nWidth + x) * 3]; // R
  105.             *p++ = (uint8_t)plus1[(y*rtmp_tool->nWidth + x) * 3 + 1]; // G
  106.             *p++ = (uint8_t)plus1[(y*rtmp_tool->nWidth + x) * 3 + 2]; // B
  107.         }
  108.     }
  109.     //将YUV buffer 填充YUV Frame    
  110.     //avpicture_fill((AVPicture*)m_pYUVFrame, (uint8_t*)rtmp_tool->yuv_buff, AV_PIX_FMT_YUV420P, rtmp_tool->nWidth, rtmp_tool->nHeight);
  111.     av_image_fill_arrays(m_pYUVFrame->data, m_pYUVFrame->linesize, (uint8_t*)rtmp_tool->yuv_buff, AV_PIX_FMT_YUV420P, c->width, c->height, 1);
  112.     // 翻转RGB图像    
  113.     //m_pRGBFrame->data[0] += m_pRGBFrame->linesize[0] * (rtmp_tool->nHeight - 1);
  114.     //m_pRGBFrame->linesize[0] *= -1;
  115.     //m_pRGBFrame->data[1] += m_pRGBFrame->linesize[1] * (rtmp_tool->nHeight / 2 - 1);
  116.     //m_pRGBFrame->linesize[1] *= -1;
  117.     //m_pRGBFrame->data[2] += m_pRGBFrame->linesize[2] * (rtmp_tool->nHeight / 2 - 1);
  118.     //m_pRGBFrame->linesize[2] *= -1;
  119.     int ret = av_frame_make_writable(m_pYUVFrame);//检测帧对象是否可读
  120.     if (ret < 0) {
  121.         printf("av_frame_make_writable %d\n", ret);
  122.         exit(1);
  123.     }
  124.     sws_scale(rtmp_tool->scxt, (uint8_t * const *)m_pRGBFrame->data, m_pRGBFrame->linesize, 0, c->height, m_pYUVFrame->data, m_pYUVFrame->linesize);
  125.     //m_pYUVFrame->pts++;
  126.     //将RGB转化为YUV    
  127.     //sws_scale(rtmp_tool->scxt, m_pRGBFrame->data, m_pRGBFrame->linesize, 0, c->height, m_pYUVFrame->data, m_pYUVFrame->linesize);
  128.     int got_packet_ptr = 0;
  129.     avpkt = av_packet_alloc();
  130.     /*if (m_pYUVFrame->pts % 10 == 0) {
  131.     m_pYUVFrame->key_frame = 1;
  132.     m_pYUVFrame->pict_type = AV_PICTURE_TYPE_I;
  133.     }
  134.     else {
  135.     m_pYUVFrame->key_frame = 0;
  136.     m_pYUVFrame->pict_type = AV_PICTURE_TYPE_P;
  137.     }*/
  138.     //int u_size = avcodec_encode_video2(c, &avpkt, m_pYUVFrame, &got_packet_ptr);
  139.     int send_ret = avcodec_send_frame(c, m_pYUVFrame);
  140.     m_pYUVFrame->pts++;
  141.     //printf("avcodec_send_frame %d\n", send_ret);
  142.     if (ret < 0)
  143.     {
  144.         printf("Error sending a frame for encoding\n");
  145.         exit(1);
  146.     }
  147.     while (ret >= 0)
  148.     {
  149.         ret = avcodec_receive_packet(c, avpkt);
  150.         if (ret != 0) {
  151.             if (ret == -11 || ret == AVERROR(EAGAIN)) {//-11
  152.                 //printf("avcodec_receive_packet AVERROR(EAGAIN)\n");
  153.             }
  154.             else if (ret == AVERROR(EINVAL)) {//-22
  155.                 printf("avcodec_receive_packet AVERROR(EINVAL)\n");
  156.             }
  157.             else {
  158.                 printf("avcodec_receive_packet error %d\n", ret);
  159.             }
  160.             return ret;
  161.         }
  162.         printf("Write packet %3(size=%5d)\n", avpkt->pts, avpkt->size);
  163.         fwrite(avpkt->data, 1, avpkt->size, rtmp_tool->f);
  164.         av_packet_unref(avpkt);
  165.     }
  166.     return 0;
  167. }

 

文章来源: blog.csdn.net,作者:网奇,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/jacke121/article/details/87105671

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。