2016-06-28 4 views
5
geschrieben werden

Ich gründe das Format Layout für das Video wie folgt zusammen:FFmpeg „movflags“> „Fast Start“ bewirkt, dass ungültige MP4-Datei

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); 

Dies ist, wie ich den Codec Kontext bin einrichten:

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 
}; 

ich verwende den folgenden Code, um die "movflags" Setup> "Fast Start" Option für den Header des Videos:

AVDictionary* options = null; 

int result = ffmpeg.av_dict_set(&options, "movflags", "faststart", 0); 

int writeHeaderResult = ffmpeg.avformat_write_header(formatContext, &options); 

Die Datei wird geöffnet und der Header wird wie folgt geschrieben:

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); 

Danach habe ich jeden Video-Frame wie folgt schreiben:

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); 
} 

Danach schreibe ich den Trailer:

int writeTrailerResult = ffmpeg.av_write_trailer(formatContext); 

Die Datei wird fertig geschrieben und alles wird geschlossen und freigegeben. Die MP4-Datei ist jedoch nicht abspielbar (selbst VLC kann sie nicht abspielen). AtomicParsley.exe zeigt auch keine Informationen über die Datei an.

Die DLLs für die AutoGen Bibliothek verwendet werden, sind:

avcodec-56.dll 
avdevice-56.dll 
avfilter-5.dll 
avformat-56.dll 
avutil-54.dll 
postproc-53.dll 
swresample-1.dll 
swscale-3.dll 
+0

Wie erstellen Sie formatContext? – szatmary

+0

Aktualisierte Frage. – williamtroup

+0

Wo ist der io Kontext? Wo werden die Daten geschrieben? Wenn Sie ein Streaming-io (wie stout) verwenden, können Sie die Datei nicht schnell starten, da die Suche in einem Stream nicht funktioniert. – szatmary

Antwort

1

Es scheint, „Fast Start“ auf seine eigenen Ursachen des Problems verwenden. Solange Sie Ihre Segmentgrößen korrekt über die "movflags" (in meinem Fall "frag_duration") einstellen, sollte es in Ordnung sein.

Außerdem wäre es besser sicherzustellen, dass beide Streams im Video korrekt synchronisiert sind. Siehe this Frage für Antworten in Bezug auf diese.

Verwandte Themen