Присвоение значений dts кодированным пакетам

У меня есть дамп данных в кодировке H264, который мне нужно поместить в контейнер mp4. Я проверил правильность закодированных данных с помощью утилиты mp4box. Файл mp4, созданный mp4box, содержал правильное видео длиной 17 секунд. Интересно, что если я попробую ffmpeg добиться того же, полученное видео будет длиною в 34 секунды и довольно дрянное (вероятно, ffmpeg пытается декодировать видео, а затем кодировать его, что приводит к потере качества видео?) В любом случае, для моего проекта Я не могу использовать подход командной строки и мне нужно придумать программный способ встроить данные в контейнер mp4.

Ниже приведен код, который я использую (я удалил проверку ошибок для краткости. Во время выполнения все вызовы завершаются успешно):

AVFormatContext* pInputFormatContext = avformat_alloc_context();
avformat_open_input(&pInputFormatContext, "Data.264", NULL, NULL);
avformat_find_stream_info(pInputFormatContext, NULL);
AVRational* pTime_base = &pInputFormatContext->streams[0]->time_base;

int nFrameRate = pInputFormatContext->streams[0]->r_frame_rate.num / pFormatCtx->streams[0]->r_frame_rate.den;
int nWidth = pInputFormatContext->streams[0]->codecpar->width;
int nHeight = pInputFormatContext->streams[0]->codecpar->height;
// nWidth = 1920, nHeight = 1080, nFrameRate = 25

// Create output objects
AVFormatContext* pOutputFormatContext = NULL;
avformat_alloc_output_context2(&pOutputFormatContext, NULL, NULL, "Destination.mp4");

AVCodec* pVideoCodec = avcodec_find_encoder(pOutputFormatContext->oformat->video_codec/*AV_CODEC_ID_264*/);
AVStream* pOutputStream = avformat_new_stream(pOutputFormatContext, NULL);
pOutputStream->id = pOutputFormatContext->nb_streams - 1;
AVCodecContext* pCodecContext = avcodec_alloc_context3(pVideoCodec);

switch (pVideoCodec->type) {
case AVMEDIA_TYPE_VIDEO:
pCodecContext->codec_id = codec_id;
pCodecContext->bit_rate = 400000;
/* Resolution must be a multiple of two. */
pCodecContext->width = nFrameWidth;
pCodecContext->height = nFrameHeight;
/* timebase: This is the fundamental unit of time (in seconds) in terms
* of which frame timestamps are represented. For fixed-fps content,
* timebase should be 1/framerate and timestamp increments should be
* identical to 1. */
pOutputStream->time_base.num = 1;
pOutputStream->time_base.den = nFrameRate;
pCodecContext->time_base = pOutputStream->time_base;
pCodecContext->gop_size = 12; /* emit one intra frame every twelve frames at most */
pCodecContext->pix_fmt = STREAM_PIX_FMT;
break;
default:
break;
}

/* copy the stream parameters to the muxer */
avcodec_parameters_from_context(pOutputStream->codecpar, pCodecContext);

avio_open(&pOutputFormatContext->pb, "Destination.mp4", AVIO_FLAG_WRITE);

// Start writing
AVDictionary* pDict = NULL;
avformat_write_header(pOutputFormatContext, &pDict);

// Process packets
AVPacket packet;
int64_t nCurrentDts = 0;
int64_t nDuration = 0;
int nReadResult = 0;

while (nReadResult == 0)
{
nReadResult = av_read_frame(m_pInputFormatContext, &packet);
// At this point, packet.dts == AV_NOPTS_VALUE.
// The duration field of the packet contains valid data

packet.flags |= AV_PKT_FLAG_KEY;
nDuration = packet.duration;
packet.dts = nCurrentDts;
packet.dts = av_rescale_q(nCurrentDts, pOutputFormatContext->streams[0]->codec->time_base, pOutputFormatContext->streams[0]->time_base);
av_interleaved_write_frame(pOutputFormatContext, &packet);
nCurrentDts += nDuration;
nDuration += packet.duration;
av_free_packet(&packet);
}

av_write_trailer(pOutputFormatContext);

Свойства для Destination.mp4 Файл, который я получаю, указывает, что его продолжительность составляет около 1 часа с частотой кадров 0. Я уверен, что виновник состоит в том, что я вычисляю значения dts для каждого пакета и использую av_rescale_q (), но у меня недостаточно понимания библиотеки avformat, чтобы понять правильный способ сделать это. Любая помощь будет оценена!

2

Решение

Задача ещё не решена.

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]