c# - nreco - FFmpeg "movflags"> "faststart" hace que se escriba un archivo MP4 no vĂ¡lido
nreco videoconverter (1)
Estoy configurando el diseño del formato del video de la siguiente manera:
AVOutputFormat* outputFormat = ffmpeg.av_guess_format(null, "output.mp4", null);
AVCodec* videoCodec = ffmpeg.avcodec_find_encoder(outputFormat->video_codec);
AVFormatContext* formatContext = ffmpeg.avformat_alloc_context();
formatContext->oformat = outputFormat;
formatContext->video_codec_id = videoCodec->id;
ffmpeg.avformat_new_stream(formatContext, videoCodec);
Así es como estoy configurando el contexto de códec:
AVCodecContext* codecContext = ffmpeg.avcodec_alloc_context3(videoCodec);
codecContext->bit_rate = 400000;
codecContext->width = 1280;
codecContext->height = 720;
codecContext->gop_size = 12;
codecContext->max_b_frames = 1;
codecContext->pix_fmt = videoCodec->pix_fmts[0];
codecContext->codec_id = videoCodec->id;
codecContext->codec_type = videoCodec->type;
codecContext->time_base = new AVRational
{
num = 1,
den = 30
};
Estoy usando el siguiente código para configurar la opción "movflags"> "faststart" para el encabezado del video:
AVDictionary* options = null;
int result = ffmpeg.av_dict_set(&options, "movflags", "faststart", 0);
int writeHeaderResult = ffmpeg.avformat_write_header(formatContext, &options);
El archivo se abre y el encabezado se escribe de la siguiente manera:
if ((formatContext->oformat->flags & ffmpeg.AVFMT_NOFILE) == 0)
{
int ioOptionResult = ffmpeg.avio_open(&formatContext->pb, "output.mp4", ffmpeg.AVIO_FLAG_WRITE);
}
int writeHeaderResult = ffmpeg.avformat_write_header(formatContext, &options);
Después de esto, escribo cada cuadro de video de la siguiente manera:
outputFrame->pts = frameIndex;
packet.flags |= ffmpeg.AV_PKT_FLAG_KEY;
packet.pts = frameIndex;
packet.dts = frameIndex;
int encodedFrame = 0;
int encodeVideoResult = ffmpeg.avcodec_encode_video2(codecContext, &packet, outputFrame, &encodedFrame);
if (encodedFrame != 0)
{
packet.pts = ffmpeg.av_rescale_q(packet.pts, codecContext->time_base, m_videoStream->time_base);
packet.dts = ffmpeg.av_rescale_q(packet.dts, codecContext->time_base, m_videoStream->time_base);
packet.stream_index = m_videoStream->index;
if (codecContext->coded_frame->key_frame > 0)
{
packet.flags |= ffmpeg.AV_PKT_FLAG_KEY;
}
int writeFrameResult = ffmpeg.av_interleaved_write_frame(formatContext, &packet);
}
Después de eso, escribo el trailer:
int writeTrailerResult = ffmpeg.av_write_trailer(formatContext);
El archivo termina de escribir y todo se cierra y se libera correctamente. Sin embargo, el archivo MP4 no se puede reproducir (incluso VLC no puede reproducirlo). AtomicParsley.exe tampoco mostrará ninguna información sobre el archivo.
Los archivos DLL utilizados para la biblioteca AutoGen son:
avcodec-56.dll
avdevice-56.dll
avfilter-5.dll
avformat-56.dll
avutil-54.dll
postproc-53.dll
swresample-1.dll
swscale-3.dll
Parece que usar "faststart" en sí mismo causa el problema. Siempre que configure los tamaños de sus segmentos correctamente a través de "movflags" ("frag_duration" en mi caso), debería estar bien.
Además, sería mejor asegurarse de que ambas transmisiones en el video estén sincronizadas correctamente. Vea esta pregunta para respuestas con respecto a esto.