FFmpeg code to extract audio and video data

Today, we begin to roll up the code. First, we use the FFmpeg API to extract the audio data of an MP4 file.

IDE

It should be the first time to do C/C + + development on Mac, and choose to use CLion development after tangle. CLion It's the IDE specially used for developing C/C + + under JetBrains. It's used to Android studio and IntelliJ IDEA, so CLion is still easy to use.

After creating a new C project, you need to import the FFmpeg library to run normally. We modify the CMakeLists.txt file of the project.

Extract audio AAC data

In fact, the main thing we need to do is to operate a file, open a file, take out part of its data from it, and then put this data into another file for saving.

Defining parameters
#include <stdio.h>
#include <libavutil/log.h>
#include <libavformat/avformat.h>

//context
AVFormatContext *fmt_ctx = NULL;
AVFormatContext *ofmt_ctx = NULL;

//Support various output file formats, MP4, FLV, 3GP, etc
AVOutputFormat *output_fmt = NULL;

//Input stream
AVStream *in_stream = NULL;

//Output stream
AVStream *out_stream = NULL;

//Store compressed data
AVPacket packet;

//Stream to copy
int audio_stream_index = -1;

1. Open the input file and extract the parameters

//Open the input file, and all the information about the input file will be saved in FMT? CTX
err_code = avformat_open_input(&fmt_ctx, src_fileName, NULL, NULL);

if (err_code < 0) {
    av_log(NULL, AV_LOG_ERROR, "cant open file:%s\n", av_err2str(err_code));
    return -1;
}

if(fmt_ctx->nb_streams<2){
      //The number of streams is less than 2, which means that the audio and video streams of this file cannot be guaranteed, and the input file has errors 
      av_log(NULL, AV_LOG_ERROR, "Input file error, less than 2 streams\n");
      exit(1);
 }

 //Get the audio stream in the file
 in_stream = fmt_ctx->streams[1];
 //parameter information
 AVCodecParameters *in_codecpar = in_stream->codecpar;

//Find the best audio stream
audio_stream_index = av_find_best_stream(fmt_ctx, AVMEDIA_TYPE_AUDIO, -1, -1, NULL, 0);
    if(audio_stream_index < 0){
        av_log(NULL, AV_LOG_DEBUG, "Failed to find the best audio stream, please check the input file!\n");
        return AVERROR(EINVAL);
}

2. Prepare output file and output stream

// Output context
ofmt_ctx = avformat_alloc_context();

//Generate the most appropriate output container based on the target filename
output_fmt = av_guess_format(NULL,dst_fileName,NULL);
if(!output_fmt){
    av_log(NULL, AV_LOG_DEBUG, "Failed to generate output container according to target!\n");
    exit(1);
}

ofmt_ctx->oformat = output_fmt;

//New output stream
 out_stream = avformat_new_stream(ofmt_ctx, NULL);
 if(!out_stream){
      av_log(NULL, AV_LOG_DEBUG, "Failed to create output stream!\n");
      exit(1);
 }

3. Data copy

3.1 parameter information

// Copy the parameter information to the output stream, we just extract the audio stream, not do the audio processing, so here is just copy
if((err_code = avcodec_parameters_copy(out_stream->codecpar, in_codecpar)) < 0 ){
    av_strerror(err_code, errors, ERROR_STR_SIZE);
    av_log(NULL, AV_LOG_ERROR,"Copy code parameter failed!, %d(%s)\n",
           err_code, errors);
}

3.2 initialize AVIOContext

//Initialize AVIOContext, which completes the file operation
if((err_code = avio_open(&ofmt_ctx->pb, dst_fileName, AVIO_FLAG_WRITE)) < 0) {
    av_strerror(err_code, errors, 1024);
    av_log(NULL, AV_LOG_DEBUG, "Could not open file %s, %d(%s)\n",
           dst_fileName,
           err_code,
           errors);
    exit(1);
}

3.3 start copying


//Initialize AVPacket, and the data we read from the file will be temporarily stored in it
av_init_packet(&packet);
packet.data = NULL;
packet.size = 0;

// Write header information
if (avformat_write_header(ofmt_ctx, NULL) < 0) {
    av_log(NULL, AV_LOG_DEBUG, "Error occurred when opening output file");
    exit(1);
}


//Every frame of data read out
while(av_read_frame(fmt_ctx, &packet) >=0 ){
    if(packet.stream_index == audio_stream_index){
        //Time base calculation, audio pts and dts are consistent
        packet.pts = av_rescale_q_rnd(packet.pts, in_stream->time_base, out_stream->time_base, (AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX));
        packet.dts = packet.pts;
        packet.duration = av_rescale_q(packet.duration, in_stream->time_base, out_stream->time_base);
        packet.pos = -1;
        packet.stream_index = 0;
        //Write package to output media file
        av_interleaved_write_frame(ofmt_ctx, &packet);
        //Reduce reference count and avoid memory leakage
        av_packet_unref(&packet);
    }
}

//Write tail information
av_write_trailer(ofmt_ctx);

//Finally, don't forget to free up memory
avformat_close_input(&fmt_ctx);
avio_close(ofmt_ctx->pb);

implement

./MyC /Users/david/Desktop/1080p.mov /Users/david/Desktop/test.aac

Extract video data

The process of extracting video information and saving it in a file, even the code, is basically the same as the audio extracted above.

//Get the audio stream or video stream in the file. All streams are in the streams array
 in_stream = fmt_ctx->streams[1];

//Find the best video stream
video_stream_index = av_find_best_stream(fmt_ctx, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0);

packet.dts = av_rescale_q_rnd(packet.dts, in_stream->time_base, out_stream->time_base, (AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX));

Basically, it's the change of some parameters. If all the processes and codes remain the same, the video data in an audio and video file can be extracted. The format of mp4, H264, etc. is so simple...

Tags: less Mac Android IntelliJ IDEA

Posted on Tue, 03 Dec 2019 17:42:22 -0500 by bmcewan