视频和音频帧的PTS和DTS计算

PTS and DTS calculation for video and audio frames

本文关键字:DTS 计算 PTS 音频 视频      更新时间:2023-10-16

我正在接收来自两个不同线程的视频H264编码数据和音频G.711 PCM编码数据,以复用/写入mov多媒体容器。

写函数签名如下:

bool WriteAudio(const unsigned char *pEncodedData, size_t iLength);
bool WriteVideo(const unsigned char *pEncodedData, size_t iLength, bool const bIFrame);

添加音频和视频流的功能如下:

AVStream* AudioVideoRecorder::AddMediaStream(enum AVCodecID codecID) {
    Log("Adding stream: %s.", avcodec_get_name(codecID));
    AVCodecContext* pCodecCtx;
    AVStream* pStream;
    /* find the encoder */
    AVCodec* codec = avcodec_find_encoder(codecID);
    if (!codec) {
        LogErr("Could not find encoder for %s", avcodec_get_name(codecID));
        return NULL;
    }
    pStream = avformat_new_stream(m_pFormatCtx, codec);
    if (!pStream) {
        LogErr("Could not allocate stream.");
        return NULL;
    }
    pStream->id = m_pFormatCtx->nb_streams - 1;
    pStream->time_base = (AVRational){1, VIDEO_FRAME_RATE};
    pCodecCtx = pStream->codec;

    switch(codec->type) {
    case AVMEDIA_TYPE_VIDEO:
        pCodecCtx->codec_id = codecID;
        pCodecCtx->bit_rate = VIDEO_BIT_RATE;
        pCodecCtx->width = PICTURE_WIDTH;
        pCodecCtx->height = PICTURE_HEIGHT;
        pCodecCtx->gop_size = VIDEO_FRAME_RATE;
        pCodecCtx->pix_fmt = PIX_FMT_YUV420P;
        m_pVideoStream = pStream;
        break;
    case AVMEDIA_TYPE_AUDIO:
        pCodecCtx->codec_id = codecID;
        pCodecCtx->sample_fmt = AV_SAMPLE_FMT_S16;
        pCodecCtx->bit_rate = 64000;
        pCodecCtx->sample_rate = 8000;
        pCodecCtx->channels = 1;
        m_pAudioStream = pStream;
        break;
    default:
        break;
    }
    /* Some formats want stream headers to be separate. */
    if (m_pOutputFmt->flags & AVFMT_GLOBALHEADER)
        m_pFormatCtx->flags |= CODEC_FLAG_GLOBAL_HEADER;
    return pStream;
}

WriteAudio(..)WriteVideo(..)函数中,我使用av_init_packet(...)创建AVPakcet,并将pEncodedDataiLength设置为packet.datapacket.size。我打印了packet.ptspacket.dts及其等价的AV_NOPTS_VALUE

现在,我如何正确计算音频和视频数据的PTS, DTS和数据包持续时间(packet.dts, packet.ptspacket.duration),以便我可以同步音频&视频和播放正确吗?我在网上看到了很多例子,但没有一个对我有意义。我是ffmpeg的新手,我的概念在某些情况下可能不正确。我想用合适的方式做这件事。

提前感谢!

编辑:在我的视频流中,没有B帧。所以,我认为PTS和DTS在这里可以保持一致。

PTS/DTS为时间戳,应设置为输入数据的时间戳。我不知道你的日期是从哪来的,但任何输入都有某种形式的时间戳与之相关。通常,输入媒体文件的时间戳或系统时钟派生的度量(如果您正在从声卡+网络摄像头等进行录制)。您应该将这些数字转换成预期的形式,然后将它们分配给AVPacket.pts/dts