2012-11-23 4 views
1

라이브 렌더링 비디오 데이터와 기존 .wav 파일을 mpg 파일로 인코딩합니다.큰 오디오 파일을 .mpg로 인코딩 할 때 av_write_frame이 실패합니다.

먼저 모든 오디오 프레임을 작성한 다음 렌더링 엔진에서 들어오는 비디오 프레임을 작성합니다. 더 작은 .wav 파일 (< 25 초)의 경우 모든 것이 완벽하게 작동합니다. 그러나 더 긴 .wav 파일을 사용하자마자 av_write_frame (오디오 프레임을 쓸 때)은 약 100 프레임을 작성한 후 -1을 반환합니다. 결코 실패하지 않는 프레임과 마지막 프레임이 결코 같은 프레임이 아닙니다. 모든 테스트 파일은 테스트 한 모든 플레이어와 완벽하게 재생할 수 있습니다.

다음은 the muxing example입니다 (다소 차이가 있음).

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" 내가 항상 어떤 프레임 후에 무엇을 얻을 수 있습니다.

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

그리고 마지막으로, 이것이 내가 모든 오디오 프레임 (I 그 루프 전에 생략는 .WAV 헤더에 대해 걱정하지 마십시오) 작성하는 루프는 다음과 같습니다

그리고 여기 내 get_audio_frame 기능입니다 :

당신이 볼 수 있듯이, 나는 패킷의 거의 모든 것을 출력하고 가능한 오류를 확인하고 있습니다. 더 긴 오디오 파일을 인코딩 할 때 av_write_frame이 실패한 것 외에는 모든 것이 완벽하게 잘된 것 같습니다. 추적중인 모든 패킷 값은 모든 프레임에 대해 100 % 동일합니다 (데이터 포인터 제외). 또한 앞에서 설명한 것처럼 동일한 절차가 짧은 fp_sound_input 파일에서도 완벽하게 작동합니다. avcodec_encode_audio2() 및 avcodec_fill_audio_frame()도 결코 실패하지 않습니다.

인코딩에 사용하는 코덱은 CODEC_ID_MPEG2VIDEO (비디오) 및 CODEC_ID_MP2 (오디오)입니다. .wav 파일은 PCM 16 LE에 저장되며 모두 동일한 인코딩을 사용합니다.

무엇이 잘못 될 수 있습니까? 내가 다시 일을 얻을 때

답변

1

봅니다하려고합니다 av_interleaved_write_frame 대신

+0

av_write_frame의를 사용합니다. 하지만 왜? 모든 오디오 프레임은 하나의 블록에 있습니다. – TheSHEEEP

+0

'av_write_frame'을 사용할 때, 패킷은 컨테이너 명세에 따라 정확하게 인터리빙되어야합니다 (MUST). 따라서, 일반적으로'av_interleaved_write_frame'을 사용하는 것이 더 좋습니다. 이 경우 인터리빙 프로세스는 자동입니다. – pogorskiy

+0

그게 다야, 고마워! 왜 작은 오디오 파일로 작동하는지 궁금합니다. ffmpeg의 짜증스러운 마법에 속하는 것 같음) – TheSHEEEP