ネットワークから h.264 ライブ ストリームを受信し (送信者はハードウェア エンコーダー)、最後の x 分間をバッファリングし、トリガーされた場合に最後の x 分間のビデオ ファイルを作成するツールを開発しています。
私のツールは、ライブ ストリームを受信し、boost::serialization で AVPackets をバッファリングすることもできます。さらに、バッファリングされた AVPackets をロードできます。
しかし、ロードされた AVPackets でビデオ ファイル (mp4) を作成/多重化しようとすると、mp4 ファイルまたは mp4 ヘッダーでエラーが発生します。mp4 ファイルを作成し、av_interleaved_write_frame() を使用してファイルにパケットを書き込むこともできます。mp4 ファイルにも妥当なサイズがあります。したがって、AVPackets がファイルに書き込まれたと思われます。
しかし、vlc などのプレーヤーで mp4 ファイルを開こうとすると、ビデオが再生されません。プレーヤーは次のようなエラーを提供します: ヘッダーが正しくなく、フレームを再生しません。しかし、writeHeader() 関数でヘッダーを AVFormatContext に書き込みます。
その理由は AVFormatContext が正しく初期化されていないためだと思いますが、ffmpeg/libav (muxing-examples) の例では問題を解決できません。
AVFormatContextを正しく初期化する方法(コード例)または他の例はありますか?
ご協力いただきありがとうございます。オルゲン
avcodec_init();
avcodec_register_all();
av_register_all();
av_log_set_level(AV_LOG_DEBUG);
char *outputFilename = "/tmp/output.mp4";
// define AVOutputFormat
AVOutputFormat *outputFormat = NULL;
outputFormat = av_guess_format("mp4", NULL, NULL);
if (!outputFormat) {
fprintf(stderr, "Could not find suitable output format\n");
return 1;
}
// define AVFormatContext
AVFormatContext *formatContext = NULL;
// lallocate the output media context
std::cout << "alloc" << std::endl;
formatContext = avformat_alloc_context();
// avformat_alloc_output_context(&formatContext, outputFormat, NULL, NULL);
if (!formatContext) {
fprintf(stderr, "Memory error\n");
return 1;
}
std::cout << "stream" << std::endl;
AVStream * video_st = av_new_stream(formatContext, 0);
AVCodec * codec = NULL;
avcodec_get_context_defaults3(video_st->codec, codec);
video_st->codec->coder_type = AVMEDIA_TYPE_VIDEO;
video_st->codec->flags = fc->streams[0]->codec->flags;
video_st->codec->sample_aspect_ratio = fc->streams[0]->codec->sample_aspect_ratio;
video_st->disposition = fc->streams[0]->disposition;
video_st->codec->codec_tag = fc->streams[0]->codec->codec_tag;
video_st->codec->bits_per_raw_sample = fc->streams[0]->codec->bits_per_raw_sample;
video_st->codec->chroma_sample_location = fc->streams[0]->codec->chroma_sample_location;
video_st->codec->codec_id = fc->streams[0]->codec->codec_id;
video_st->codec->codec_tag = fc->streams[0]->codec->codec_tag;
video_st->codec->time_base = fc->streams[0]->codec->time_base;
video_st->codec->extradata = fc->streams[0]->codec->extradata;
video_st->codec->extradata_size = fc->streams[0]->codec->extradata_size;
video_st->codec->pix_fmt = fc->streams[0]->codec->pix_fmt;
video_st->codec->width = fc->streams[0]->codec->width;
video_st->codec->height = fc->streams[0]->codec->height;
video_st->codec->sample_aspect_ratio = fc->streams[0]->codec->sample_aspect_ratio;
std::cout << "file" << std::endl;
avio_open(&formatContext->pb, outputFilename, AVIO_FLAG_WRITE);
std::cout << "header" << std::endl;
avformat_write_header(formatContext, NULL);
// av_write_header(formatContext);
// loop to write AVPackets with av_write_frame
プログラムは avformat_write_header(formatContext, NULL) の後にメモリ エラーでクラッシュします。avformat_alloc_output_context2() の代わりに avformat_alloc_output_context() も試しましたが、どちらの関数も機能しません。だから私は avformat_alloc_context() を使用しました(上記を参照)
割り当ての問題があると思いますが、なぜ avformat_alloc_output_context2 または avformat_alloc_output_context を使用できないのですか? 誰かがここで私の問題を理解できますか?