A few days did not write FFmpeg code, today while there is free to pull down FFmpeg cut video code, I am also learning while writing, if there are mistakes, please point out in the comments, learn from each other.

Train of thought

Said the function implementation is also very simple, given a starting time, an end time, open the video file, and then put in a container each flow starting from the starting time, until the end time of the data copied to the output stream, then the output stream is saved as a container, so you can see a video file after shearing.

Code implementation

The first step is to define parameters

AVFormatContext *ifmt_ctx = NULL;
AVFormatContext *ofmt_ctx = NULL;
AVOutputFormat *ofmt = NULL;
AVPacket pkt;

doubleStart_seconds;// Start time
doubleEnd_seconds;// End time
const char* in_filename;// Enter the file
const char* out_filename;// Output file
Copy the code

The second step initializes the context

avformat_open_input(&ifmt_ctx, in_filename, 0.0);

// The avformat_alloc_context and av_guess_format functions are essentially called to create the output context and generate the most appropriate output container according to the output file suffix
avformat_alloc_output_context2(&ofmt_ctx, NULL.NULL, out_filename); 
ofmt = ofmt_ctx->oformat;
Copy the code

Step 3 Create a copy of the flow and parameters

for (i = 0; i < ifmt_ctx->nb_streams; i++) {
        AVStream *in_stream = ifmt_ctx->streams[i];
        AVStream *out_stream = avformat_new_stream(ofmt_ctx, NULL);
        if(! out_stream) {fprintf(stderr."Failed allocating output stream\n");
            ret = AVERROR_UNKNOWN;
            goto end;
        }
        avcodec_parameters_copy(out_stream->codecpar, in_stream->codecpar);
        out_stream->codecpar->codec_tag = 0;
    }
Copy the code

Step 4 Open the output file

avio_open(&ofmt_ctx->pb, out_filename, AVIO_FLAG_WRITE);
Copy the code

Step 5 Process and write data

// Write header information
ret = avformat_write_header(ofmt_ctx, NULL);
if (ret < 0) {
    fprintf(stderr."Error occurred when opening output file\n");
    goto end;
}

// Jump to the specified frame
ret = av_seek_frame(ifmt_ctx, - 1, start_seconds * AV_TIME_BASE, AVSEEK_FLAG_ANY);
if (ret < 0) {
        fprintf(stderr."Error seek\n");
        goto end;
}

// Apply space according to the number of streams and initialize all to 0
int64_t *dts_start_from = malloc(sizeof(int64_t) * ifmt_ctx->nb_streams);
memset(dts_start_from, 0.sizeof(int64_t) * ifmt_ctx->nb_streams);

int64_t *pts_start_from = malloc(sizeof(int64_t) * ifmt_ctx->nb_streams);
memset(pts_start_from, 0.sizeof(int64_t) * ifmt_ctx->nb_streams);

while (1) {
        AVStream *in_stream, *out_stream;

        // Read data
        ret = av_read_frame(ifmt_ctx, &pkt);
        if (ret < 0)
            break;

        in_stream = ifmt_ctx->streams[pkt.stream_index];
        out_stream = ofmt_ctx->streams[pkt.stream_index];

        // If the time exceeds the time to intercept, exit the loop
        if (av_q2d(in_stream->time_base) * pkt.pts > end_seconds) {
            av_packet_unref(&pkt);
            break;
        }

        // Save the start DTS and PTS of each captured stream as the start time for later timebase conversion
        if (dts_start_from[pkt.stream_index] == 0) {
            dts_start_from[pkt.stream_index] = pkt.dts;
        }
        if (pts_start_from[pkt.stream_index] == 0) {
            pts_start_from[pkt.stream_index] = pkt.pts;
        }

        // Time base conversion
        pkt.pts = av_rescale_q_rnd(pkt.pts - pts_start_from[pkt.stream_index], in_stream->time_base, out_stream->time_base, AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX);
        pkt.dts = av_rescale_q_rnd(pkt.dts - dts_start_from[pkt.stream_index], in_stream->time_base,out_stream->time_base, AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX);
        
        if (pkt.pts < 0) {
            pkt.pts = 0;
        }
        if (pkt.dts < 0) {
            pkt.dts = 0;
        }

        pkt.duration = (int) av_rescale_q((int64_t) pkt.duration, in_stream->time_base, out_stream->time_base);
        pkt.pos = - 1;

        Pkt.pts < pkt.dts will cause an exception in the program, so if we drop the frame in question, it will not have a big impact.
        if (pkt.pts < pkt.dts) {
            continue;
        }
    
        ret = av_interleaved_write_frame(ofmt_ctx, &pkt);
        if (ret < 0) {
            fprintf(stderr."Error write packet\n");
            break;
        }

        av_packet_unref(&pkt);
    }

// Release resources
free(dts_start_from);
free(pts_start_from);

// Write the end of the file
av_write_trailer(ofmt_ctx);
Copy the code

This is the whole processing process, or relatively simple.