this 예제에서 MP4 비디오를 만드는 법을 배우고 있습니다.이 예제는 fly에서 생성 된 더미 소스 데이터의 오디오 인코딩을 보여줍니다. 파일에서 오디오를 인코딩해야합니다. . 나는 많은 예제를 확인했으며 그 중 대부분은 동일하거나 별도의 오디오 인코딩을 보여줍니다. 내 시행 착오 과정에서 오디오 및 비디오 frames.I에 대해 동일한 AVFormatContext 사용하고 있습니다. 나는 옳은 일인지, 아니면 두 별도의 컨텍스트가 있어야합니까? 지금까지 비디오 인코딩 괜찮아요 있지만 오디오 스트림 있어요 AVPacket이 올바른 오디오 스트림 인덱스를 찾을 수 없으므로 실패합니다. 여기FFmpeg로 오디오와 비디오 파일을 Muxing
void open_audio(AVFormatContext *oc, AVCodec **codec, AVStream **st ,enum AVCodecID codec_id){
// AVCodecContext *c;
int ret;
// c = st->codec;
*codec = avcodec_find_encoder(codec_id);
if (!(*codec)) {
fprintf(stderr, "Could not find encoder for '%s'\n",avcodec_get_name(codec_id));
}
/* open it */
if(avformat_open_input(&oc,_audioInName.c_str(),NULL,NULL) !=0){
Msg::PrintErrorMsg("Error opening audio file");
}
AVStream* audioStream = NULL;
// Find the audio stream (some container files can have multiple streams in them)
for (uint32_t i = 0; i < oc->nb_streams; ++i)
{
if (oc->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO)
{
audioStream = oc->streams[i];
break;
}
}
if (audioStream == NULL)
{
Msg::PrintErrorMsg("Could not find any audio stream in the file");
}
*st =audioStream;
AVCodecContext *c = audioStream->codec;
c->codec = *codec;//avcodec_find_decoder(c->codec_id);
audioStream->id = 1;
c->sample_fmt = AV_SAMPLE_FMT_S16;
c->bit_rate = 64000;
c->sample_rate = 44100;
c->channels = 1;
if (oc->oformat->flags & AVFMT_GLOBALHEADER){
c->flags |= CODEC_FLAG_GLOBAL_HEADER;
}
if (c->codec == NULL)
{
Msg::PrintErrorMsg("Couldn't find a proper decoder");
}
ret = avcodec_open2(c, *codec, NULL);
if (ret < 0) {
Msg::PrintErrorMsg("Could not open audio codec\n");
}
}
"OC는"뿐만 아니라 비디오 스트림을 초기화하는 데 사용 같은 상황은 다음과 같습니다 는 여기에 설치 오디오 스트림 방법이다.
void write_audio_frame(AVFormatContext *oc, AVStream *st){
AVCodecContext *c;
AVPacket pkt = { 0 }; // data and size must be 0;
AVFrame *frame = avcodec_alloc_frame();
int got_packet, ret;
av_init_packet(&pkt);
c = st->codec;
/////
// get_audio_frame(samples, audio_input_frame_size, c->channels);
////Read the packet:
while(av_read_frame(oc,&pkt) == 0){
if(pkt.stream_index ==st->index){
// Try to decode the packet into a frame
int frameFinished = 0;
avcodec_decode_audio4(c, frame, &frameFinished, &pkt);
// Some frames rely on multiple packets, so we have to make sure the frame is finished before
// we can use it
if (frameFinished){
assert(frameFinished);
ret = avcodec_encode_audio2(c, &pkt, frame, &got_packet);
if (ret < 0) {
Msg::PrintErrorMsg("Error encoding audio frame\n");
}
if (!got_packet){
printf("failed to aquire packet");
}
pkt.stream_index = st->index;
/* Write the compressed frame to the media file. */
ret = av_interleaved_write_frame(oc, &pkt);
if (ret != 0) {
Msg::PrintErrorMsg("Error while writing audio frame.");
}
}
}
}
}
av_free_packet(&pkt);
avcodec_free_frame(&frame);
}
는 것은 내가 결코이 문을 통과하지 :
그 다음이 같은 오디오 프레임을 쓰기 위해 노력하고 있어요 "(pkt.stream_index는 == ST-이> 색인)이"패킷 스트림 인덱스입니다. 아무도 내가 잘못한 곳을 지적 할 수 있습니까?업데이트 : 인코딩을위한 입력 오디오 스트림을 열 관리 않았다 그러나 나는 오디오를 인코딩 할 수 및 비디오 내가 PTS와 DTS는 아마도 문제의 원인입니다 무엇을보고 하나의 output.From에 스트림
현재 muxing.c 예제를 기반으로 pts를 계산하지만 오디오에서는 전혀 작동하지 않습니다. 여기
내가 그것을 사용하는 방법이다 : 나는 audio_pts가 video_pts에 도달 결코 오디오 인코딩 루프에서 생각하면, 어떻게 든
while(frame_count < _streamDurationNBFrames-1){
uint8_t *frameToWrite =_frames.front();
// Compute current audio and video time. ///
if (audio_st){
audio_pts = (double)audioIn_st->pts.val * audioIn_st->time_base.num/audioIn_st->time_base.den;
}
else{
audio_pts = 0.0;
}
if (video_st){
video_pts = (double)video_st->pts.val * video_st->time_base.num/ video_st->time_base.den;
}else{
video_pts = 0.0;
}
if ((!audio_st || audio_pts >= _streamDuration) && (!video_st || video_pts >= _streamDuration)){
break;
}
if (audio_st && audio_pts < video_pts) {
av_read_frame(informat, &pkt);//read audio from input stream
Msg::PrintMsg("Encode audio here...");
//================== AUDIO ENCODE HERE
outpkt.data = pkt.data;
outpkt.size = pkt.size;
outpkt.stream_index = pkt.stream_index;
outpkt.flags |= AV_PKT_FLAG_KEY;
outpkt.pts = pkt.pts;
outpkt.dts =pkt.dts;
if(av_interleaved_write_frame(oc, &outpkt) < 0)
{
Msg::PrintErrorMsg("Fail Audio Write ");
}
else
{
audio_st->codec->frame_number++;
}
av_free_packet(&outpkt);
av_free_packet(&pkt);
}else{
//================== VIDEO ENCODE HERE
write_video_frame(oc, video_st,frameToWrite);
frame->pts += av_rescale_q(1, video_st->codec->time_base, video_st->time_base);
}
///at last delete this frame:
_frames.pop();
delete frameToWrite; ///deallocate the written frame!
}
을 항상 0입니다 :
audio_pts = (double)audio_st->pts.val * audio_st->time_base.num/audio_st->time_base.den; is always zero because (double)audio_st->pts.val returns zero.
그래서 기본적으로 내가 같은 질문을 다시 한 번 묻습니다 : 외부 파일에서 오디오를 가져 오는 경우 muxing을 수행하는 방법?
Btw, 아래의 대답은 오디오 및 비디오 스트림이 동일한 파일에서 오는 것으로 가정하기 때문에 도움이되지 않지만 내 경우에는 오디오 만 외부 소스에서 가져옵니다.
내가 설정 점을, 그냥 넣어하지 않은 그러게, 내가 필요한 것은 추가하는 것입니다했다 오디오는 인코딩 중입니다. 오디오는 AAC 미디어 파일에서 가져옵니다.이 예제에서는 많은 감사를 표합니다. 시도해 본 모든 내용이 작동하지 않을 때까지 체크 아웃 할 것입니다. –
FFMPEG 예제에서 볼 수 있듯이 인코딩 전에 avcodec_open2()를 통해 오디오 및 비디오 코덱을 열지 않아야합니까? –
인코딩을 위해 예전에 avcodec_open2()를 호출해야합니다. 제 경우에는 스트림 복사본을 사용하고 있었기 때문에 사용하지 않았습니다. 그러나 당신은해야 할 것입니다. – praks411