当前位置: 首页 > 知识库问答 >
问题:

FFMPEG-PTS和dts对视频没有适当增加,但对音频有增加

左丘昕
2023-03-14
Application provided invalid, non monotonically increasing dts to muxer in stream 0

非单调递增的dts是什么意思?

如何使用libavformat以相同的编解码器连接2个视频文件?

流中dts到muxer的非单调递增

typedef struct Video {
    char* filename;
    AVFormatContext* inputContext;
    AVFormatContext* outputContext;
    AVCodec* videoCodec;
    AVCodec* audioCodec;
    AVStream* inputStream;
    AVStream* outputStream;
    AVCodecContext* videoCodecContext_I; // Input
    AVCodecContext* audioCodecContext_I; // Input
    AVCodecContext* videoCodecContext_O; // Output
    AVCodecContext* audioCodecContext_O; // Output
    int videoStream;
    int audioStream;
    SwrContext* swrContext;
} Video;

typedef struct ClipSequence {
    VideoList* videos;
    AVFormatContext* outputContext;
    AVStream* outputStream;
    int64_t lastpts, lastdts;
    int64_t currentpts, currentdts;
} ClipSequence;
int decodeVideoSequence(ClipSequence* sequence, Video* video, AVPacket* packet, AVFrame* frame) {
    int response = avcodec_send_packet(video->videoCodecContext_I, packet);
    if (response < 0) {
        printf("[ERROR] Failed to send video packet to decoder\n");
        return response;
    }
    while (response >= 0) {
        response = avcodec_receive_frame(video->videoCodecContext_I, frame);
        if (response == AVERROR(EAGAIN) || response == AVERROR_EOF) {
            break;
        } else if (response < 0) {
            printf("[ERROR] Failed to receive video frame from decoder\n");
            return response;
        }
        if (response >= 0) {
            // Do stuff and encode
            sequence->currentpts = packet->pts; // Store decoded packet's pts and dts
            sequence->currentdts = packet->dts;
            if (encodeVideoSequence(sequence, video, frame) < 0) {
                printf("[ERROR] Failed to encode new video\n");
                return -1;
            }
        }
        av_frame_unref(frame);
    }
    return 0;
}

int encodeVideoSequence(ClipSequence* sequence, Video* video, AVFrame* frame) {
    AVPacket* packet = av_packet_alloc();
    if (!packet) {
        printf("[ERROR] Could not allocate memory for video output packet\n");
        return -1;
    }
    int response = avcodec_send_frame(video->videoCodecContext_O, frame);
    if (response < 0) {
        printf("[ERROR] Failed to send video frame for encoding\n");
        return response;
    }
    while (response >= 0) {
        response = avcodec_receive_packet(video->videoCodecContext_O, packet);
        if (response == AVERROR(EAGAIN) || response == AVERROR_EOF) {
            break;
        } else if (response < 0) {
            printf("[ERROR] Failed to receive video packet from encoder\n");
            return response;
        }
        // Set packet to have pts and dts based on the previous video's pts and dts
        packet->flags |= AV_PKT_FLAG_KEY;
        packet->pts = sequence->currentpts + sequence->lastpts;
        packet->dts = sequence->currentdts + sequence->lastdts;
        packet->stream_index = video->videoStream;
        packet->duration = 1000; // 60 fps
        response = av_interleaved_write_frame(sequence->outputContext, packet);
        if (response < 0) {
            printf("[ERROR] Failed to write video packet\n");
            break;
        }
    }
    av_packet_unref(packet);
    av_packet_free(&packet);
    return 0;
}
int readSequenceFrames(ClipSequence* sequence, Video* video, AVPacket* packet, AVFrame* frame) {
    if (!packet) {
        printf("[ERROR] Packet not allocated to be read\n");
        return -1;
    }
    if (!frame) {
        printf("[ERROR] Frame not allocated to be read\n");
        return -1;
    }
    // Sets video and audio codec context parameters
    if (prepareVideoOutStream(video) < 0) {
        printf("[ERROR] Failed to prepare output video stream\n");
        return -1;
    }
    if (prepareAudioOutStream(video) < 0) {
        printf("[ERROR] Failed to prepare output audio stream\n");
        return -1;
    }
    // Prepares audio resampling
    if (initResampler(video->audioCodecContext_I, video->audioCodecContext_O, &(video->swrContext)) < 0) {
        printf("[ERROR] Failed to init audio resampler\n");
        return -1;
    }
    // Read packets
    int frameNum = 0;
    while (av_read_frame(video->inputContext, packet) >= 0) {
        printf("[READ] Reading frame %i\n", frameNum);
        if (packet->stream_index == video->videoStream) {
            if (decodeVideoSequence(sequence, video, packet, frame) < 0) {
                printf("[ERROR] Failed to decode and encode video\n");
                return -1;
            }
        } else if (packet->stream_index == video->audioStream) {
            if (decodeAudioSequence(sequence, video, packet, frame) < 0) {
                printf("[ERROR] Failed to decode and encode audio\n");
                return -1;
            }
        }
        av_packet_unref(packet);
        frameNum++;
    }
    // Increment pts and dts by the last pts and dts in the current video
    sequence->lastpts += sequence->currentpts;
    sequence->lastdts += sequence->currentdts;
    return 0;
}

我相信当我增加pts和DTS时,我有正确的逻辑。我不知道我到底错过了什么。

谢了。

共有1个答案

宗波涛
2023-03-14
   // Increment pts and dts by the last pts and dts in the current video
    sequence->lastpts += sequence->currentpts;
    sequence->lastdts += sequence->currentdts;

这是不对的。首先,现在忽略PTS,只处理DTS。

DTS不是一个相对数,它是一个绝对数。将递增的数字加在一起会创建一个指数序列。例如:如果这是一个30 fps的视频,时基是1/30,每帧DTS将前进一个。例如0、1、2、3、4、5、6、7、9

如果你继续把它们加在一起,你会得到:0,1,3,6,10,15,21,28,36,45

否则,当需要增加1帧时,此帧将具有与前一帧相同的DTS

下一个临时秘书处:

PTS不是单调的,可以在时间上倒退。您不能以这种方式跟踪它,因为下一个PTS可能是一个较低的时间戳。要解决这个问题,您需要将PTS转换为CTS,然后返回:

auto cts = packet->pts - packet->dts
packet->dts = // Whatever you are updating the dts to
packet->pts = packet->dts + cts
 类似资料:
  • 我正在从两个不同的线程接收视频H264编码数据和音频G.711 PCM编码数据,以mux/写入多媒体容器。 writer函数签名如下所示: 提前感谢! 编辑:在我的视频流中,没有B帧。所以,我认为这里PTS和DTS可以保持不变。

  • 我正在尝试mux H264编码数据和G711 PCM数据到多媒体容器。我从编码数据创建,最初视频/音频帧的PTS和DTS值等效于。所以我使用当前时间信息计算了DTS。我的密码- 我添加了这样的流- 编辑: 根据Ronald S.Bultje的建议,我所理解的是: 应该设置为现在音频和视频流现在都在同一时间基本单位中。 另外,如果我想使用视频流时基作为和音频流时基作为,正确的代码应该是什么样子? 编

  • 我想从视频中提取对齐的音频流。目标是获得与视频精确对齐的音频序列。 问题:视频和音频序列不对齐。输出音频持续时间比视频输入短。 要复制的脚本: 我的尝试(没有成功): 按照此答案中的建议添加 添加,同时导出视频(链接) 在Audacity中打开。那里的持续时间是 在VLC中打开。持续时间: 显式设置帧率 其他视频文件 如果能给我一些建议,我将不胜感激。非常感谢。

  • 当从avi转码到mp4(x264)时,我遇到了fps问题。最终问题出在PTS和DTS值上,所以在AV_INTLEAVED_WRITE_FRAME函数之前添加的第12-15行: 看了很多帖子我还是不明白: =1/25和=1/12800。第一个是我设置的,但我不知道为什么和谁设置了12800?我注意到,在第(7)行=1/90000之前,紧接着它变成了1/12800,为什么?当我从avi转码到avi时,

  • 在Android上使用phonegap创建了一个应用程序。 一切都很好,除了视频不会以任何形式播放。只有音频。 错误: E/libEGL(1441):在没有当前上下文的情况下调用OpenGL ES API(每个线程记录一次) 尝试使用非嵌入式视频,不同的格式,不同的嵌入,改变config.xml设置,基本上大约30-40种不同的解决方案。并且已经为此工作了40多个小时。 大约11个月前,我在Pho