• ffmpeg 开发第一例


    站在巨人的肩膀上最简单的基于FFMPEG的封装格式转换器(无编解码)_mp4remuxer_雷霄骅的博客-CSDN博客

    在作者的示例上,修正了在ffmpeg6.0.1上运行,有些方法过时了.没有其它的修改.

    1. const char *in_filename = "/Users/archko/Movie/健身气功八段锦-clip.mp4";
    2. const char *out_filename = "/Users/archko/Movie/code.mp4";
    3. const AVOutputFormat *ofmt = NULL;
    4. //输入对应一个AVFormatContext,输出对应一个AVFormatContext
    5. //(Input AVFormatContext and Output AVFormatContext)
    6. AVFormatContext *ifmt_ctx = NULL, *ofmt_ctx = NULL;
    7. AVPacket pkt;
    8. int ret, i;
    9. // 输入(Input)
    10. ret = avformat_open_input(&ifmt_ctx, in_filename, 0, 0);
    11. if (ret < 0) {
    12. printf("Could not open input file.");
    13. return 0;
    14. }
    15. ret = avformat_find_stream_info(ifmt_ctx, 0);
    16. if (ret < 0) {
    17. printf("Failed to retrieve input stream information");
    18. return 0;
    19. }
    20. av_dump_format(ifmt_ctx, 0, in_filename, 0);
    21. //输出(Output)
    22. avformat_alloc_output_context2(&ofmt_ctx, NULL, NULL, out_filename);
    23. if (!ofmt_ctx) {
    24. printf("Could not create output context\n");
    25. ret = AVERROR_UNKNOWN;
    26. return 0;
    27. }
    28. ofmt = ofmt_ctx->oformat;
    29. for (i = 0; i < ifmt_ctx->nb_streams; i++) {
    30. //根据输入流创建输出流(Create output AVStream according to input AVStream)
    31. AVStream *in_stream = ifmt_ctx->streams[i];
    32. const AVCodec *codec = avcodec_find_decoder(in_stream->codecpar->codec_id);
    33. AVStream *out_stream = avformat_new_stream(ofmt_ctx, codec);
    34. if (!out_stream) {
    35. printf("Failed allocating output stream\n");
    36. ret = AVERROR_UNKNOWN;
    37. return 0;
    38. }
    39. //复制AVCodecContext的设置(Copy the settings of AVCodecContext)
    40. AVCodecContext *codec_ctx = avcodec_alloc_context3(codec);
    41. ret = avcodec_parameters_to_context(codec_ctx, in_stream->codecpar);
    42. if (ret < 0) {
    43. printf("Failed to copy context from input to output stream codec context\n");
    44. return 0;
    45. }
    46. ret = avcodec_parameters_from_context(out_stream->codecpar, codec_ctx);
    47. if (ret < 0) {
    48. printf("Failed to copy codec context to out_stream codecpar context\n");
    49. return 0;
    50. }
    51. out_stream->codecpar->codec_tag = 0;
    52. //leixiaohua1020 在这是有这段操作的,6.0不需要这样,然后正常复制视频
    53. //if (ofmt_ctx->oformat->flags & AVFMT_GLOBALHEADER) {
    54. // out_stream->codecpar->codec_tag |= AV_CODEC_FLAG_GLOBAL_HEADER;
    55. //}
    56. }
    57. //输出一下格式------------------
    58. av_dump_format(ofmt_ctx, 0, out_filename, 1);
    59. //打开输出文件(Open output file)
    60. if (!(ofmt->flags & AVFMT_NOFILE)) {
    61. ret = avio_open(&ofmt_ctx->pb, out_filename, AVIO_FLAG_WRITE);
    62. if (ret < 0) {
    63. printf("Could not open output file '%s'", out_filename);
    64. return 0;
    65. }
    66. }
    67. //写文件头(Write file header)
    68. ret = avformat_write_header(ofmt_ctx, NULL);
    69. if (ret < 0) {
    70. printf("Error occurred when opening output file\n");
    71. return 0;
    72. }
    73. int frame_index = 0;
    74. while (1) {
    75. AVStream *in_stream, *out_stream;
    76. //获取一个AVPacket(Get an AVPacket)
    77. ret = av_read_frame(ifmt_ctx, &pkt);
    78. if (ret < 0)
    79. break;
    80. in_stream = ifmt_ctx->streams[pkt.stream_index];
    81. out_stream = ofmt_ctx->streams[pkt.stream_index];
    82. /* copy packet */
    83. //转换PTS/DTS(Convert PTS/DTS)
    84. pkt.pts = av_rescale_q_rnd(pkt.pts, in_stream->time_base, out_stream->time_base,
    85. (AVRounding) (AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX));
    86. pkt.dts = av_rescale_q_rnd(pkt.dts, in_stream->time_base, out_stream->time_base,
    87. (AVRounding) (AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX));
    88. pkt.duration = av_rescale_q(pkt.duration, in_stream->time_base, out_stream->time_base);
    89. pkt.pos = -1;
    90. //写入(Write)
    91. ret = av_interleaved_write_frame(ofmt_ctx, &pkt);
    92. if (ret < 0) {
    93. printf("Error muxing packet\n");
    94. break;
    95. }
    96. //printf("Write %8d frames to output file\n", frame_index);
    97. av_packet_unref(&pkt);
    98. frame_index++;
    99. }
    100. //写文件尾(Write file trailer)
    101. av_write_trailer(ofmt_ctx);
    102. end:
    103. avformat_close_input(&ifmt_ctx);
    104. /* close output */
    105. if (ofmt_ctx && !(ofmt->flags & AVFMT_NOFILE)) {
    106. avio_close(ofmt_ctx->pb);
    107. }
    108. avformat_free_context(ofmt_ctx);
    109. if (ret < 0 && ret != AVERROR_EOF) {
    110. printf("Error occurred.\n");
    111. return -1;
    112. }
    113. printf("Copy success.\n");
    114. return 0;

    xcode的开发实在不习惯,用的是clion,cmake,vscode.下一篇,clion创建项目,导入ffmpeg依赖

  • 相关阅读:
    SpringBoot整合阿里云发送短信 (demo)
    Dubbo命令行详解
    如何利用Requestly提升前端开发与测试的效率,让你事半功倍?
    力扣第216 组合总和 ||| c++ 回溯 + 注释
    人生如何破局?
    python flask接口字段存在性校验函数(http接口字段校验)(返回提示缺少的字段信息)validate_fields()
    mysql面试题(史上最全面试题,精心整理100家互联网企业,面试必过)
    leetcode数据结构与算法刷题(三)
    Paparazzi: Surface Editing by way of Multi-View Image Processing
    springboot之@ImportResource:导入Spring配置文件~
  • 原文地址:https://blog.csdn.net/archko/article/details/132921048