C++音视频03:媒体信息打印、提取音视频、转封装、剪辑 ...

打印 上一主题 下一主题

主题 960|帖子 960|积分 2880

版本:FFMpeg6.0
媒体信息打印

  1. #include <libavformat/avformat.h>
  2. #include <libavutil/log.h>
  3. int main (int argc, char *argv[]) {
  4.     AVFormatContext *fmt_cxt = NULL;
  5.     int ret;
  6.     av_log_set_level(AV_LOG_INFO);
  7.     ret = avformat_open_input(&fmt_cxt, "/root/resource/1.mp4", NULL, NULL);
  8.     if (ret < 0) {
  9.         av_log(NULL, AV_LOG_ERROR, "Can't open file: %s", av_err2str(ret));
  10.         return -1;
  11.     }
  12.         // 打印媒体信息
  13.     av_dump_format(fmt_cxt, 0, "/root/resource/1.mp4", 0);
  14.     avformat_close_input(&fmt_cxt);
  15.    
  16.     return 0;
  17. }
复制代码
提取音视频

音频和视频的区别在于av_find_best_stream时将AVMEDIA_TYPE_VIDEO改为AVMEDIA_TYPE_AUDIO
  1. #include <libavformat/avformat.h>
  2. #include <libavutil/log.h>
  3. #include <libavutil/avutil.h>
  4. int main (int argc, char *argv[]) {
  5.     // 1. 处理参数
  6.     char *src;
  7.     char *dst;
  8.     int ret;
  9.     int idx = -1;
  10.     AVFormatContext *pFmtCtx = NULL;
  11.     AVFormatContext *oFmtCtx = NULL;
  12.     const AVOutputFormat *outFmt = NULL;
  13.     AVStream *outStream = NULL;
  14.     AVStream *inStream = NULL;
  15.     AVPacket pkt;
  16.     av_log_set_level(AV_LOG_DEBUG);
  17.     if (argc < 3) {
  18.         av_log(NULL, AV_LOG_ERROR, "argument must be more than 3\n");
  19.         exit(-1);
  20.     }
  21.     src = argv[1];
  22.     dst = argv[2];
  23.     // 2. 打开多媒体文件
  24.     ret = avformat_open_input(&pFmtCtx, src, NULL, NULL);
  25.     if (ret < 0) {
  26.         av_log(NULL, AV_LOG_ERROR, "%s\n", av_err2str(ret));
  27.         exit(-1);
  28.     }
  29.     // 3. 从多媒体文件中找到音频流
  30.     idx = av_find_best_stream(pFmtCtx, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0);
  31.     if (idx < 0) {
  32.         av_log(pFmtCtx, AV_LOG_ERROR, "Does not include audio stream\n");
  33.         goto _ERROR;
  34.     }
  35.     // 4. 打开目的文件的上下文
  36.     oFmtCtx = avformat_alloc_context();
  37.     if (!oFmtCtx) {
  38.         av_log(pFmtCtx, AV_LOG_ERROR, "No memory\n");
  39.         goto _ERROR;
  40.     }
  41.     outFmt = av_guess_format(NULL, dst, NULL);
  42.     oFmtCtx->oformat = outFmt;
  43.     // 5. 为目的文件创建新的音频流
  44.     outStream = avformat_new_stream(oFmtCtx, NULL);
  45.     // 6. 设置输出视频参数
  46.     inStream = pFmtCtx->streams[idx];
  47.     avcodec_parameters_copy(outStream->codecpar, inStream->codecpar);
  48.     // 设置为0,会自动去找对应的编码器
  49.     outStream->codecpar->codec_tag = 0;
  50.     ret = avio_open2(&oFmtCtx->pb, dst, AVIO_FLAG_WRITE, NULL, NULL);
  51.     if (ret < 0) {
  52.         av_log(oFmtCtx, AV_LOG_ERROR, "%s\n", av_err2str(ret));
  53.         goto _ERROR;
  54.     }
  55.    
  56.     // 7. 写多媒体文件头到目的文件
  57.     ret = avformat_write_header(oFmtCtx, NULL);
  58.     if (ret < 0) {
  59.         av_log(oFmtCtx, AV_LOG_ERROR, "%s\n", av_err2str(ret));
  60.         goto _ERROR;
  61.     }
  62.     // 8. 从源多媒体文件中读音频数据到目的文件中
  63.     while (av_read_frame(pFmtCtx, &pkt) >= 0) {
  64.         if (pkt.stream_index == idx) {
  65.             // 修改时间戳
  66.             pkt.pts = av_rescale_q_rnd(pkt.pts, inStream->time_base, outStream->time_base, (AV_ROUND_INF | AV_ROUND_PASS_MINMAX));
  67.             pkt.dts = av_rescale_q_rnd(pkt.dts, inStream->time_base, outStream->time_base, (AV_ROUND_INF | AV_ROUND_PASS_MINMAX));
  68.             pkt.duration = av_rescale_q(pkt.duration, inStream->time_base, outStream->time_base);
  69.             pkt.stream_index = 0;
  70.             // 设置成-1,自己会去计算
  71.             pkt.pos = -1;
  72.             av_interleaved_write_frame(oFmtCtx, &pkt);
  73.             av_packet_unref(&pkt);
  74.         }
  75.     }
  76.     // 9. 写多媒体文件尾到目的文件
  77.     av_write_trailer(oFmtCtx);
  78.     // 10. 将申请的资源释放掉
  79. _ERROR:
  80.     if (pFmtCtx) {
  81.         avformat_close_input(&pFmtCtx);
  82.         pFmtCtx = NULL;
  83.     }   
  84.     if (oFmtCtx->pb) {
  85.         avio_close(oFmtCtx->pb);
  86.     }
  87.     if (oFmtCtx) {
  88.         avformat_free_context(oFmtCtx);
  89.         oFmtCtx = NULL;
  90.     }
  91.     return 0;
  92. }
复制代码
转封装

  1. #include <libavformat/avformat.h>
  2. #include <libavutil/log.h>
  3. #include <libavutil/avutil.h>
  4. int main (int argc, char *argv[]) {
  5.     // 1. 处理参数
  6.     char *src;
  7.     char *dst;
  8.     int *stream_map = NULL;
  9.     int stream_idx = 0;
  10.     int ret;
  11.     int idx = -1;
  12.     int i = 0;
  13.     AVFormatContext *pFmtCtx = NULL;
  14.     AVFormatContext *oFmtCtx = NULL;
  15.     const AVOutputFormat *outFmt = NULL;
  16.    
  17.     AVPacket pkt;
  18.     av_log_set_level(AV_LOG_DEBUG);
  19.     if (argc < 3) {
  20.         av_log(NULL, AV_LOG_ERROR, "argument must be more than 3\n");
  21.         exit(-1);
  22.     }
  23.     src = argv[1];
  24.     dst = argv[2];
  25.     // 2. 打开多媒体文件
  26.     ret = avformat_open_input(&pFmtCtx, src, NULL, NULL);
  27.     if (ret < 0) {
  28.         av_log(NULL, AV_LOG_ERROR, "%s\n", av_err2str(ret));
  29.         exit(-1);
  30.     }
  31.    
  32.     // 3. 打开目的文件的上下文
  33.     avformat_alloc_output_context2(&oFmtCtx, NULL, NULL, dst);
  34.     if (!oFmtCtx) {
  35.         av_log(NULL, AV_LOG_ERROR, "NO MEMORY\n");
  36.         goto _ERROR;
  37.     }
  38.     stream_map = av_calloc(pFmtCtx->nb_streams, sizeof(int));
  39.     if (!stream_map) {
  40.         av_log(NULL, AV_LOG_ERROR, "NO MEMORY\n");
  41.         goto _ERROR;
  42.     }
  43.     for (i = 0; i < pFmtCtx->nb_streams; ++i) {
  44.         AVStream *outStream = NULL;
  45.         AVStream *inStream = pFmtCtx->streams[i];
  46.         AVCodecParameters *inCodecPar = inStream->codecpar;
  47.         if (inCodecPar->codec_type != AVMEDIA_TYPE_AUDIO &&
  48.             inCodecPar->codec_type != AVMEDIA_TYPE_VIDEO &&
  49.             inCodecPar->codec_type != AVMEDIA_TYPE_SUBTITLE) {
  50.             stream_map[i] = -1;
  51.             continue;
  52.         }
  53.         stream_map[i] = stream_idx++;
  54.         // 4. 为目的文件创建新的音频流
  55.         outStream = avformat_new_stream(oFmtCtx, NULL);
  56.         if (!outStream) {
  57.             av_log(oFmtCtx, AV_LOG_ERROR, "NO MEMORY\n");
  58.             goto _ERROR;
  59.         }
  60.         avcodec_parameters_copy(outStream->codecpar, inStream->codecpar);
  61.         // 设置为0,会自动去找对应的编码器
  62.         outStream->codecpar->codec_tag = 0;
  63.     }
  64.    
  65.     ret = avio_open2(&oFmtCtx->pb, dst, AVIO_FLAG_WRITE, NULL, NULL);
  66.     if (ret < 0) {
  67.         av_log(oFmtCtx, AV_LOG_ERROR, "%s\n", av_err2str(ret));
  68.         goto _ERROR;
  69.     }
  70.    
  71.     // 5. 写多媒体文件头到目的文件
  72.     ret = avformat_write_header(oFmtCtx, NULL);
  73.     if (ret < 0) {
  74.         av_log(oFmtCtx, AV_LOG_ERROR, "%s\n", av_err2str(ret));
  75.         goto _ERROR;
  76.     }
  77.     // 6. 从源多媒体文件中读音频数据到目的文件中
  78.     while (av_read_frame(pFmtCtx, &pkt) >= 0) {
  79.         AVStream *outStream = NULL;
  80.         AVStream *inStream = NULL;
  81.         
  82.         if (stream_map[pkt.stream_index] < 0) {
  83.             av_packet_unref(&pkt);
  84.             continue;
  85.         }
  86.         inStream = pFmtCtx->streams[pkt.stream_index];
  87.         pkt.stream_index = stream_map[pkt.stream_index];
  88.         outStream = oFmtCtx->streams[pkt.stream_index];
  89.         av_packet_rescale_ts(&pkt, inStream->time_base, outStream->time_base);
  90.         // 设置成-1,自己会去计算
  91.         pkt.pos = -1;
  92.         av_interleaved_write_frame(oFmtCtx, &pkt);
  93.         av_packet_unref(&pkt);
  94.         
  95.     }
  96.     // 7. 写多媒体文件尾到目的文件
  97.     av_write_trailer(oFmtCtx);
  98.     // 8. 将申请的资源释放掉
  99. _ERROR:
  100.     if (pFmtCtx) {
  101.         avformat_close_input(&pFmtCtx);
  102.         pFmtCtx = NULL;
  103.     }   
  104.     if (oFmtCtx->pb) {
  105.         avio_close(oFmtCtx->pb);
  106.     }
  107.     if (oFmtCtx) {
  108.         avformat_free_context(oFmtCtx);
  109.         oFmtCtx = NULL;
  110.     }
  111.     if (stream_map) {
  112.         av_free(stream_map);
  113.     }
  114.     return 0;
  115. }
复制代码
剪辑

  1. #include <libavformat/avformat.h>
  2. #include <libavutil/log.h>
  3. #include <libavutil/avutil.h>
  4. #include <stdlib.h>
  5. int main (int argc, char *argv[]) {
  6.     // 1. 处理参数
  7.     char *src;
  8.     char *dst;
  9.     int *stream_map = NULL;
  10.     int stream_idx = 0;
  11.     int ret;
  12.     int idx = -1;
  13.     int i = 0;
  14.     double startTime = 0;
  15.     double endTime = 0;
  16.     int64_t *dts_start_time = NULL;
  17.     int64_t *pts_start_time = NULL;
  18.     AVFormatContext *pFmtCtx = NULL;
  19.     AVFormatContext *oFmtCtx = NULL;
  20.     const AVOutputFormat *outFmt = NULL;
  21.    
  22.     AVPacket pkt;
  23.     av_log_set_level(AV_LOG_DEBUG);
  24.     // cut src dst start end
  25.     if (argc < 5) {
  26.         av_log(NULL, AV_LOG_ERROR, "argument must be more than 5\n");
  27.         exit(-1);
  28.     }
  29.     src = argv[1];
  30.     dst = argv[2];
  31.     startTime = atof(argv[3]);
  32.     endTime = atof(argv[4]);
  33.     av_log(NULL, AV_LOG_INFO, "hello\n");
  34.     // 2. 打开多媒体文件
  35.     ret = avformat_open_input(&pFmtCtx, src, NULL, NULL);
  36.     if (ret < 0) {
  37.         av_log(NULL, AV_LOG_ERROR, "%s\n", av_err2str(ret));
  38.         exit(-1);
  39.     }
  40.    
  41.     // 4. 打开目的文件的上下文
  42.     avformat_alloc_output_context2(&oFmtCtx, NULL, NULL, dst);
  43.     if (!oFmtCtx) {
  44.         av_log(NULL, AV_LOG_ERROR, "NO MEMORY\n");
  45.         goto _ERROR;
  46.     }
  47.     stream_map = av_calloc(pFmtCtx->nb_streams, sizeof(int));
  48.     if (!stream_map) {
  49.         av_log(NULL, AV_LOG_ERROR, "NO MEMORY\n");
  50.         goto _ERROR;
  51.     }
  52.     for (i = 0; i < pFmtCtx->nb_streams; ++i) {
  53.         AVStream *outStream = NULL;
  54.         AVStream *inStream = pFmtCtx->streams[i];
  55.         AVCodecParameters *inCodecPar = inStream->codecpar;
  56.         if (inCodecPar->codec_type != AVMEDIA_TYPE_AUDIO &&
  57.             inCodecPar->codec_type != AVMEDIA_TYPE_VIDEO &&
  58.             inCodecPar->codec_type != AVMEDIA_TYPE_SUBTITLE) {
  59.             stream_map[i] = -1;
  60.             continue;
  61.         }
  62.         stream_map[i] = stream_idx++;
  63.         // 5. 为目的文件创建新的音频流
  64.         outStream = avformat_new_stream(oFmtCtx, NULL);
  65.         if (!outStream) {
  66.             av_log(oFmtCtx, AV_LOG_ERROR, "NO MEMORY\n");
  67.             goto _ERROR;
  68.         }
  69.         avcodec_parameters_copy(outStream->codecpar, inStream->codecpar);
  70.         // 设置为0,会自动去找对应的编码器
  71.         outStream->codecpar->codec_tag = 0;
  72.     }
  73.    
  74.     ret = avio_open2(&oFmtCtx->pb, dst, AVIO_FLAG_WRITE, NULL, NULL);
  75.     if (ret < 0) {
  76.         av_log(oFmtCtx, AV_LOG_ERROR, "%s\n", av_err2str(ret));
  77.         goto _ERROR;
  78.     }
  79.    
  80.     // 7. 写多媒体文件头到目的文件
  81.     ret = avformat_write_header(oFmtCtx, NULL);
  82.     if (ret < 0) {
  83.         av_log(oFmtCtx, AV_LOG_ERROR, "%s\n", av_err2str(ret));
  84.         goto _ERROR;
  85.     }
  86.     // seek
  87.     ret = av_seek_frame(pFmtCtx, -1, startTime * AV_TIME_BASE, AVSEEK_FLAG_BACKWARD);
  88.     if (ret < 0) {
  89.         av_log(oFmtCtx, AV_LOG_ERROR, "%s\n", av_err2str(ret));
  90.         goto _ERROR;
  91.     }
  92.     dts_start_time = av_calloc(pFmtCtx->nb_streams, sizeof(int64_t));
  93.     pts_start_time = av_calloc(pFmtCtx->nb_streams, sizeof(int64_t));
  94.     for (int t = 0; t < pFmtCtx->nb_streams; ++t) {
  95.         dts_start_time[t] = -1;
  96.         pts_start_time[t] = -1;
  97.     }
  98.     // 8. 从源多媒体文件中读音频数据到目的文件中
  99.     while (av_read_frame(pFmtCtx, &pkt) >= 0) {
  100.         AVStream *outStream = NULL;
  101.         AVStream *inStream = NULL;
  102.         
  103.         if (dts_start_time[pkt.stream_index] == -1 && pkt.dts > 0) {
  104.             dts_start_time[pkt.stream_index] = pkt.dts;
  105.         }
  106.         if (pts_start_time[pkt.stream_index] == -1 && pkt.pts > 0) {
  107.             pts_start_time[pkt.stream_index] = pkt.pts;
  108.         }
  109.         if (stream_map[pkt.stream_index] < 0) {
  110.             av_packet_unref(&pkt);
  111.             continue;
  112.         }
  113.         pkt.pts = pkt.pts - pts_start_time[pkt.stream_index];
  114.         pkt.dts = pkt.dts - dts_start_time[pkt.stream_index];
  115.         if (pkt.dts > pkt.pts) {
  116.             pkt.pts = pkt.dts;
  117.         }
  118.         inStream = pFmtCtx->streams[pkt.stream_index];
  119.         if (av_q2d(inStream->time_base) * pkt.pts > endTime) {
  120.             av_log(oFmtCtx, AV_LOG_INFO, "success\n");
  121.             break;
  122.         }
  123.         pkt.stream_index = stream_map[pkt.stream_index];
  124.         outStream = oFmtCtx->streams[pkt.stream_index];
  125.         av_packet_rescale_ts(&pkt, inStream->time_base, outStream->time_base);
  126.         // 设置成-1,自己会去计算
  127.         pkt.pos = -1;
  128.         av_interleaved_write_frame(oFmtCtx, &pkt);
  129.         av_packet_unref(&pkt);
  130.         
  131.     }
  132.     // 9. 写多媒体文件尾到目的文件
  133.     av_write_trailer(oFmtCtx);
  134.     // 10. 将申请的资源释放掉
  135. _ERROR:
  136.     if (pFmtCtx) {
  137.         avformat_close_input(&pFmtCtx);
  138.         pFmtCtx = NULL;
  139.     }   
  140.     if (oFmtCtx->pb) {
  141.         avio_close(oFmtCtx->pb);
  142.     }
  143.     if (oFmtCtx) {
  144.         avformat_free_context(oFmtCtx);
  145.         oFmtCtx = NULL;
  146.     }
  147.     if (stream_map) {
  148.         av_free(stream_map);
  149.     }
  150.     if (pts_start_time) {
  151.         av_free(pts_start_time);
  152.     }
  153.     if (dts_start_time) {
  154.         av_free(dts_start_time);
  155.     }
  156.     return 0;
  157. }
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

勿忘初心做自己

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表