ライブレンダリングされたビデオデータと既存の.wavファイルをmpgファイルにエンコードしています。
そのためには、最初にすべてのオーディオフレームを書き込み、次にレンダリングエンジンから入ってくるビデオフレームを書き込みます。小さい.wavファイル(<25秒)の場合、すべてが完全に正常に機能します。しかし、より長い.wavファイルを使用するとすぐに、av_write_frame(オーディオフレームを書き込む場合)は、約100フレームを書き込んだ後、-1を返します。失敗するフレームと同じになることはなく、最後のフレームになることもありません。すべてのテストファイルは、私がテストしたどのプレーヤーでも完全に再生できます。
私は多重化の例に従っています(多かれ少なかれ)。
オーディオフレームを書き込む私の関数は次のとおりです。
void write_audio_frame( Cffmpeg_dll * ptr, AVFormatContext *oc, AVStream *st, int16_t sample_val )
{
AVCodecContext *c;
AVPacket pkt = { 0 }; // data and size must be 0;
AVFrame *frame = avcodec_alloc_frame();
int got_packet;
av_init_packet(&pkt);
c = st->codec;
get_audio_frame(ptr, ptr->samples, ptr->audio_input_frame_size, c->channels);
frame->nb_samples = ptr->audio_input_frame_size;
int result = avcodec_fill_audio_frame(frame, c->channels, c->sample_fmt,
(uint8_t *) ptr->samples,
ptr->audio_input_frame_size *
av_get_bytes_per_sample(c->sample_fmt) *
c->channels, 0);
if (result != 0)
{
av_log(c, AV_LOG_ERROR, "Error filling audio frame. Code: %i\n", result);
exit(1);
}
result = avcodec_encode_audio2(c, &pkt, frame, &got_packet);
if (result != 0)
{
av_log(c, AV_LOG_ERROR, "Error encoding audio. Code: %i\n", result);
exit(1);
}
if (c->coded_frame && c->coded_frame->pts != AV_NOPTS_VALUE)
pkt.pts= av_rescale_q(c->coded_frame->pts, c->time_base, st->time_base);
pkt.flags |= AV_PKT_FLAG_KEY;
pkt.stream_index= st->index;
av_log(c, AV_LOG_ERROR, "Got? %i Pts: %i Dts: %i Flags: %i Side Elems: %i Size: %i\n",
got_packet, pkt.pts, pkt.dts, pkt.flags, pkt.side_data_elems, pkt.size);
/* write the compressed frame in the media file */
result = av_write_frame(oc, &pkt);
if (result != 0)
{
av_log(c, AV_LOG_ERROR, "Error while writing audio frame. Result: %i\n", result);
exit(1);
}
}
したがって、「オーディオフレームの書き込み中にエラーが発生しました。結果:-1」は、いくつかのフレームの後に常に表示されるものです。
そして、これが私のget_audio_frame関数です。
void get_audio_frame( Cffmpeg_dll* ptr, int16_t* samples, int frame_size, int nb_channels, int16_t sample_val )
{
fread( samples, sizeof( int16_t ), frame_size * nb_channels, ptr->fp_sound_input );
};
そして最後に、これは私がすべてのオーディオフレームを書き込むループです(.wavヘッダーについて心配する必要はありません、そのループの前にスキップしました):
while (!feof(ptr->fp_sound_input))
{
write_audio_frame( ptr, ptr->oc, ptr->audio_st, -1 );
}
ご覧のとおり、私はパケット内のほとんどすべてを出力しており、エラーの可能性をチェックしています。長いオーディオファイルをエンコードしているときにav_write_frameが失敗することを除けば、すべてが完全に正常に見えます。私が追跡しているすべてのパケット値は、すべてのフレームで100%同じです(明らかにデータポインタを除く)。また、前述のように、同じ手順は、より短いfp_sound_inputファイルに対しても問題なく機能します。avcodec_encode_audio2()およびavcodec_fill_audio_frame()も失敗することはありません。
エンコードに使用するコーデックは、CODEC_ID_MPEG2VIDEO(ビデオ)とCODEC_ID_MP2(オーディオ)です。.wavファイルはPCM16LEで保存されます(すべてまったく同じエンコーディングを使用します)。
ここで何が間違っている可能性がありますか?