Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- AVFormatContext *create_format_context(String const &inputFile)
- {
- AVFormatContext *ctx{nullptr};
- FFMPEG_CALL(avformat_open_input(&ctx, inputFile.begin(), nullptr, nullptr));
- return ctx;
- }
- AVFormatContext *create_format_context(DataProvider *pDataProvider)
- {
- AVFormatContext *ctx{avformat_alloc_context()};
- assert(ctx);
- size_t bufSize{8 * 1024 * 1024};
- uint8_t *avBuffer{(uint8_t*)av_malloc(bufSize)};
- assert(avBuffer);
- ctx->pb = avio_alloc_context(avBuffer,
- bufSize,
- 0,
- pDataProvider,
- DataProvider::read,
- nullptr,
- nullptr);
- assert(ctx->pb);
- ctx->flags |= AVFMT_FLAG_CUSTOM_IO;
- FFMPEG_CALL(avformat_open_input(&ctx, nullptr, nullptr, nullptr));
- return ctx;
- }
- inline AVBSFContext* init_bsf(char const *bsf_name, AVCodecParameters const *params)
- {
- AVBitStreamFilter const *bsf{av_bsf_get_by_name(bsf_name)};
- assert(bsf);
- AVBSFContext *bsfc;
- FFMPEG_CALL(av_bsf_alloc(bsf, &bsfc));
- FFMPEG_CALL(avcodec_parameters_copy(bsfc->par_in, params));
- FFMPEG_CALL(av_bsf_init(bsfc));
- return bsfc;
- }
- Muxer::~Muxer() { close(); }
- void Muxer::open(String const &inFile,
- String const &outFile,
- AVCodecID codec)
- {
- open(create_format_context(inFile), outFile, codec);
- }
- void Muxer::open(DataProvider *pDataProvider,
- String const &outFile,
- AVCodecID codec)
- {
- open(create_format_context(pDataProvider), outFile, codec);
- }
- void Muxer::open(AVFormatContext *pInCtx,
- String const & outFile,
- AVCodecID codec)
- {
- if (!pInCtx) {
- throw std::invalid_argument(
- "Parameter pInCtx must a valid AVFormatContext!");
- }
- pInFmtCtx = pInCtx;
- dstFile = outFile;
- codec = codec;
- start();
- }
- void Muxer::close() {
- if (pInFmtCtx) {
- if (pkt.data) { av_packet_unref(&pkt); }
- if (pktFiltered.data) { av_packet_unref(&pktFiltered); }
- avformat_close_input(&pInFmtCtx);
- if (pInFmtCtx->pb) { avio_context_free(&pInFmtCtx->pb); }
- avformat_free_context(pInFmtCtx);
- }
- if (pOutFmtCtx) {
- if (pOutFmtCtx->pb) { avio_close(pOutFmtCtx->pb); }
- avformat_free_context(pOutFmtCtx);
- }
- }
- void Muxer::start() {
- // may be necessary to initialize the streams with in the context
- FFMPEG_CALL(avformat_find_stream_info(pInFmtCtx, nullptr));
- // alloc and open context for the output file
- FFMPEG_CALL(avformat_alloc_output_context2(
- &pOutFmtCtx, nullptr, nullptr, dstFile.begin()));
- FFMPEG_CALL(avio_open(&pOutFmtCtx->pb, dstFile.begin(), AVIO_FLAG_WRITE));
- for (int i = 0; i < pInFmtCtx->nb_streams; i++) {
- if (pInFmtCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
- // create output stream
- AVStream *inStream = pInFmtCtx->streams[i];
- AVStream *outStream =
- avformat_new_stream(pOutFmtCtx, inStream->codec->codec);
- assert(outStream);
- // store the according stream indices
- videoIndexIn = i;
- videoIndexOut = outStream->index;
- // initialize newly created output stream
- FFMPEG_CALL(
- avcodec_copy_context(outStream->codec, inStream->codec));
- outStream->codec->codec_tag = 0;
- if (pOutFmtCtx->oformat->flags & AVFMT_GLOBALHEADER) {
- outStream->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;
- }
- break;
- }
- }
- // write header information
- FFMPEG_CALL(avformat_write_header(pOutFmtCtx, nullptr));
- // pre-initialize the packets
- av_init_packet(&pkt);
- pkt.data = nullptr;
- pkt.size = 0;
- av_init_packet(&pktFiltered);
- pktFiltered.data = nullptr;
- pktFiltered.size = 0;
- // Bitstream filter
- if (codec == AV_CODEC_ID_HEVC) {
- pBSFContext = init_bsf("hevc_mp4toannexb", pInFmtCtx->streams[videoIndexIn]->codecpar);
- } else if (codec == AV_CODEC_ID_H264) {
- pBSFContext = init_bsf("h264_mp4toannexb",
- pInFmtCtx->streams[videoIndexIn]->codecpar);
- } else {
- throw std::invalid_argument("Only HEVC and AVC are supported!");
- }
- }
- void Muxer::progress() {
- if (pkt.data) { av_packet_unref(&pkt); }
- if (pktFiltered.data) { av_packet_unref(&pktFiltered); }
- while(av_read_frame(pInFmtCtx, &pkt) >= 0) {
- if (pkt.stream_index != videoIndexIn) break;
- curPts = pkt.pts;
- FFMPEG_CALL(av_bsf_send_packet(pBSFContext, &pkt));
- FFMPEG_CALL(av_bsf_receive_packet(pBSFContext, &pktFiltered));
- fprintf(
- stdout, "Write 1 Packet. size:%5d\tpts:%8d\n", pkt.size, pkt.pts);
- FFMPEG_CALL(av_interleaved_write_frame(pOutFmtCtx, &pkt));
- av_packet_unref(&pkt);
- av_packet_unref(&pktFiltered);
- }
- }
- void Muxer::finish() { av_write_trailer(pOutFmtCtx); }
- bool Muxer::isOpen() const { return true; }
Add Comment
Please, Sign In to add comment