0

I'm trying to remux individual tracks from a FLAC file using the FFmpeg libraries. I get the starting timestamps from a Cue sheet, I seek to the timestamps using avformat_seek_file. However after writing the packets to output files, they only have data from the beginning of the input file.

This is the code snippet which opens the input FLAC and also creates an output AVFormatContext for each track. I'm guessing the issue is avformat_seek_file, it doesn't seem to do anything, since even though I seek to the beginning of a track, the output file contains data from the beginning of the input.

    for(int i = 0; i <= sheet.ntracks; i++) {
        sheet.avfmtctx = avformat_alloc_context();
        if(avformat_open_input(&sheet.avfmtctx, sheet.file, NULL, NULL) < 0) {
            fprintf(stderr,
                    "avformat_open_input(): failed to open %s\n",
                    sheet.file);
            return 1;
        }
        int audio_stream_idx = -1;
        for(int i = 0; i < sheet.avfmtctx->nb_streams; i++) {
            if(sheet.avfmtctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
                audio_stream_idx = i;
                break;
            }
        }
        avformat_find_stream_info(sheet.avfmtctx, NULL);
        AVFormatContext *output;
        char *filepath = title_to_filepath(&sheet.tracks[i], sheet.file);
        avformat_alloc_output_context2(&output, NULL, NULL, filepath);
        AVStream *out_audio_stream = avformat_new_stream(output, NULL);
        avcodec_parameters_copy(out_audio_stream->codecpar,
                                sheet.avfmtctx->streams[audio_stream_idx]->codecpar);

        if(avio_open(&output->pb, filepath, AVIO_FLAG_WRITE) < 0) {
            fprintf(stderr, "Failed to open %s for writing\n", filepath);
            return 1;
        }
        if(avformat_write_header(output, NULL) < 0) {
            fprintf(stderr, "avformat_write_header() failed\n");
            return 1;
        }
        int64_t current_frame = sheet.tracks[i].index;
        int64_t next_track_index = (i < sheet.ntracks) ?
                                   sheet.tracks[i + 1].index :
                                   INT64_MAX;
        if(avformat_seek_file(sheet.avfmtctx,
                           -1,
                           INT64_MIN,
                           current_frame,
                           current_frame,
                           0) < 0) {
            fprintf(stderr, "Failed to seek to the index of track %d\n", i);
            avformat_free_context(sheet.avfmtctx);
            sheet.avfmtctx = NULL;
            av_write_trailer(output);
            avio_closep(&output->pb);
            avformat_free_context(output);
            free(filepath);
            continue;
        }
        AVPacket *pkt = av_packet_alloc();
        int64_t pts_diff = AV_NOPTS_VALUE, dts_diff = AV_NOPTS_VALUE;
        while(current_frame < next_track_index && !avio_feof(output->pb)) {
            int ret;
            if((ret = av_read_frame(sheet.avfmtctx, pkt)) < 0) {
                if(ret != AVERROR_EOF)
                    fprintf(stderr, "av_read_frame() failed: %s\n", av_err2str(ret));
                break;
            }
            if(pkt->stream_index != audio_stream_idx)
                continue;
            // runs only once
            if(pts_diff == AV_NOPTS_VALUE && dts_diff == AV_NOPTS_VALUE) {
                pts_diff = pkt->pts;
                dts_diff = pkt->dts;
            }

            pkt->stream_index = 0; // first and only stream
            pkt->pts -= pts_diff;
            pkt->dts -= dts_diff;
            pkt->pos = -1;
            av_interleaved_write_frame(output, pkt);

            current_frame++;
        }

        avformat_free_context(sheet.avfmtctx);
        sheet.avfmtctx = NULL;

        av_write_trailer(output);
        av_packet_free(&pkt);
        avio_closep(&output->pb);
        avformat_free_context(output);

        free(filepath);
    }

current_frame and next_track_index are calculated from the INDEX lines in the Cue sheet: MM * 60 * 75 + SS * 75 + FF. Can someone tell me what I'm doing wrong, and how to get the data I need from the input?

0 Answers0