Guest User

muxer_source

a guest
May 2nd, 2021
220
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.75 KB | None | 0 0
  1. AVFormatContext *create_format_context(String const &inputFile)
  2. {
  3.     AVFormatContext *ctx{nullptr};
  4.     FFMPEG_CALL(avformat_open_input(&ctx, inputFile.begin(), nullptr, nullptr));
  5.     return ctx;
  6. }
  7.  
  8. AVFormatContext *create_format_context(DataProvider *pDataProvider)
  9. {
  10.     AVFormatContext *ctx{avformat_alloc_context()};
  11.     assert(ctx);
  12.  
  13.     size_t   bufSize{8 * 1024 * 1024};
  14.     uint8_t *avBuffer{(uint8_t*)av_malloc(bufSize)};
  15.     assert(avBuffer);
  16.  
  17.     ctx->pb = avio_alloc_context(avBuffer,
  18.                                  bufSize,
  19.                                  0,
  20.                                  pDataProvider,
  21.                                  DataProvider::read,
  22.                                  nullptr,
  23.                                  nullptr);
  24.     assert(ctx->pb);
  25.  
  26.     ctx->flags |= AVFMT_FLAG_CUSTOM_IO;
  27.  
  28.     FFMPEG_CALL(avformat_open_input(&ctx, nullptr, nullptr, nullptr));
  29.     return ctx;
  30. }
  31.  
  32. inline AVBSFContext* init_bsf(char const *bsf_name, AVCodecParameters const *params)
  33. {
  34.     AVBitStreamFilter const *bsf{av_bsf_get_by_name(bsf_name)};
  35.     assert(bsf);
  36.  
  37.     AVBSFContext *bsfc;
  38.     FFMPEG_CALL(av_bsf_alloc(bsf, &bsfc));
  39.     FFMPEG_CALL(avcodec_parameters_copy(bsfc->par_in, params));
  40.     FFMPEG_CALL(av_bsf_init(bsfc));
  41.     return bsfc;
  42. }
  43.  
  44. Muxer::~Muxer() { close(); }
  45.  
  46. void Muxer::open(String const &inFile,
  47.                  String const &outFile,
  48.                  AVCodecID     codec)
  49. {
  50.     open(create_format_context(inFile), outFile, codec);
  51. }
  52.  
  53. void Muxer::open(DataProvider *pDataProvider,
  54.                  String const &outFile,
  55.                  AVCodecID     codec)
  56. {
  57.     open(create_format_context(pDataProvider), outFile, codec);
  58. }
  59.  
  60. void Muxer::open(AVFormatContext *pInCtx,
  61.                  String const &   outFile,
  62.                  AVCodecID codec)
  63. {
  64.     if (!pInCtx) {
  65.         throw std::invalid_argument(
  66.             "Parameter pInCtx must a valid AVFormatContext!");
  67.     }
  68.     pInFmtCtx = pInCtx;
  69.     dstFile   = outFile;
  70.     codec     = codec;
  71.  
  72.     start();
  73. }
  74.  
  75. void Muxer::close() {
  76.     if (pInFmtCtx) {
  77.         if (pkt.data) { av_packet_unref(&pkt); }
  78.         if (pktFiltered.data) { av_packet_unref(&pktFiltered); }
  79.  
  80.         avformat_close_input(&pInFmtCtx);
  81.         if (pInFmtCtx->pb) { avio_context_free(&pInFmtCtx->pb); }
  82.         avformat_free_context(pInFmtCtx);
  83.     }
  84.  
  85.     if (pOutFmtCtx) {
  86.         if (pOutFmtCtx->pb) { avio_close(pOutFmtCtx->pb); }
  87.         avformat_free_context(pOutFmtCtx);
  88.     }
  89. }
  90.  
  91. void Muxer::start() {
  92.     // may be necessary to initialize the streams with in the context
  93.     FFMPEG_CALL(avformat_find_stream_info(pInFmtCtx, nullptr));
  94.  
  95.     // alloc and open context for the output file
  96.     FFMPEG_CALL(avformat_alloc_output_context2(
  97.         &pOutFmtCtx, nullptr, nullptr, dstFile.begin()));
  98.     FFMPEG_CALL(avio_open(&pOutFmtCtx->pb, dstFile.begin(), AVIO_FLAG_WRITE));
  99.  
  100.     for (int i = 0; i < pInFmtCtx->nb_streams; i++) {
  101.         if (pInFmtCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
  102.             // create output stream
  103.             AVStream *inStream = pInFmtCtx->streams[i];
  104.             AVStream *outStream =
  105.                 avformat_new_stream(pOutFmtCtx, inStream->codec->codec);
  106.             assert(outStream);
  107.  
  108.             // store the according stream indices
  109.             videoIndexIn  = i;
  110.             videoIndexOut = outStream->index;
  111.  
  112.             // initialize newly created output stream
  113.             FFMPEG_CALL(
  114.                 avcodec_copy_context(outStream->codec, inStream->codec));
  115.             outStream->codec->codec_tag = 0;
  116.             if (pOutFmtCtx->oformat->flags & AVFMT_GLOBALHEADER) {
  117.                 outStream->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;
  118.             }
  119.             break;
  120.         }
  121.     }
  122.  
  123.     // write header information
  124.     FFMPEG_CALL(avformat_write_header(pOutFmtCtx, nullptr));
  125.  
  126.     // pre-initialize the packets
  127.     av_init_packet(&pkt);
  128.     pkt.data = nullptr;
  129.     pkt.size = 0;
  130.     av_init_packet(&pktFiltered);
  131.     pktFiltered.data = nullptr;
  132.     pktFiltered.size = 0;
  133.  
  134.     // Bitstream filter
  135.     if (codec == AV_CODEC_ID_HEVC) {
  136.         pBSFContext = init_bsf("hevc_mp4toannexb", pInFmtCtx->streams[videoIndexIn]->codecpar);
  137.     } else if (codec == AV_CODEC_ID_H264) {
  138.         pBSFContext = init_bsf("h264_mp4toannexb",
  139.                                pInFmtCtx->streams[videoIndexIn]->codecpar);
  140.     } else {
  141.         throw std::invalid_argument("Only HEVC and AVC are supported!");
  142.     }
  143. }
  144.  
  145. void Muxer::progress() {
  146.     if (pkt.data) { av_packet_unref(&pkt); }
  147.     if (pktFiltered.data) { av_packet_unref(&pktFiltered); }
  148.  
  149.     while(av_read_frame(pInFmtCtx, &pkt) >= 0) {
  150.         if (pkt.stream_index != videoIndexIn) break;
  151.         curPts = pkt.pts;
  152.  
  153.         FFMPEG_CALL(av_bsf_send_packet(pBSFContext, &pkt));
  154.         FFMPEG_CALL(av_bsf_receive_packet(pBSFContext, &pktFiltered));
  155.  
  156.         fprintf(
  157.             stdout, "Write 1 Packet. size:%5d\tpts:%8d\n", pkt.size, pkt.pts);
  158.         FFMPEG_CALL(av_interleaved_write_frame(pOutFmtCtx, &pkt));
  159.  
  160.  
  161.         av_packet_unref(&pkt);
  162.         av_packet_unref(&pktFiltered);
  163.     }
  164. }
  165.  
  166. void Muxer::finish() { av_write_trailer(pOutFmtCtx); }
  167.  
  168. bool Muxer::isOpen() const { return true; }
  169.  
Add Comment
Please, Sign In to add comment