Commit 98ffc5c5 authored by michael's avatar michael

flush audio encoder buffers at the end

fix vorbis in nut again


git-svn-id: file:///var/local/repositories/ffmpeg/trunk@3244 9553f0bf-9b14-0410-a0b8-cfaf0461ba5b
parent c000a5ea
...@@ -582,6 +582,7 @@ static void fill_pad_region(AVPicture* img, int height, int width, ...@@ -582,6 +582,7 @@ static void fill_pad_region(AVPicture* img, int height, int width,
} }
} }
static uint8_t *video_buffer= NULL; //FIXME rename, its used for audio too at the end
static void do_video_out(AVFormatContext *s, static void do_video_out(AVFormatContext *s,
AVOutputStream *ost, AVOutputStream *ost,
...@@ -592,7 +593,6 @@ static void do_video_out(AVFormatContext *s, ...@@ -592,7 +593,6 @@ static void do_video_out(AVFormatContext *s,
int nb_frames, i, ret; int nb_frames, i, ret;
AVFrame *final_picture, *formatted_picture; AVFrame *final_picture, *formatted_picture;
AVFrame picture_format_temp, picture_crop_temp; AVFrame picture_format_temp, picture_crop_temp;
static uint8_t *video_buffer= NULL;
uint8_t *buf = NULL, *buf1 = NULL; uint8_t *buf = NULL, *buf1 = NULL;
AVCodecContext *enc, *dec; AVCodecContext *enc, *dec;
enum PixelFormat target_pixfmt; enum PixelFormat target_pixfmt;
...@@ -1206,6 +1206,58 @@ static int output_packet(AVInputStream *ist, int ist_index, ...@@ -1206,6 +1206,58 @@ static int output_packet(AVInputStream *ist, int ist_index,
av_free(buffer_to_free); av_free(buffer_to_free);
} }
discard_packet: discard_packet:
if (pkt == NULL) {
/* EOF handling */
for(i=0;i<nb_ostreams;i++) {
ost = ost_table[i];
if (ost->source_index == ist_index) {
AVCodecContext *enc= &ost->st->codec;
os = output_files[ost->file_index];
if(ost->st->codec.codec_type == CODEC_TYPE_AUDIO && enc->frame_size <=1)
continue;
if(ost->st->codec.codec_type == CODEC_TYPE_VIDEO && (os->oformat->flags & AVFMT_RAWPICTURE))
continue;
if (ost->encoding_needed) {
for(;;) {
AVPacket pkt;
av_init_packet(&pkt);
pkt.stream_index= ost->index;
switch(ost->st->codec.codec_type) {
case CODEC_TYPE_AUDIO:
ret = avcodec_encode_audio(enc, video_buffer, VIDEO_BUFFER_SIZE, NULL);
audio_size += ret;
pkt.flags |= PKT_FLAG_KEY;
break;
case CODEC_TYPE_VIDEO:
ret = avcodec_encode_video(enc, video_buffer, VIDEO_BUFFER_SIZE, NULL);
video_size += ret;
if(enc->coded_frame && enc->coded_frame->key_frame)
pkt.flags |= PKT_FLAG_KEY;
if (ost->logfile && enc->stats_out) {
fprintf(ost->logfile, "%s", enc->stats_out);
}
break;
default:
ret=-1;
}
if(ret<=0)
break;
pkt.data= video_buffer;
pkt.size= ret;
if(enc->coded_frame)
pkt.pts= enc->coded_frame->pts;
av_interleaved_write_frame(os, &pkt);
}
}
}
}
}
return 0; return 0;
fail_decode: fail_decode:
return -1; return -1;
......
...@@ -294,6 +294,8 @@ extern int motion_estimation_method; ...@@ -294,6 +294,8 @@ extern int motion_estimation_method;
#define CODEC_CAP_TRUNCATED 0x0008 #define CODEC_CAP_TRUNCATED 0x0008
/* codec can export data for HW decoding (XvMC) */ /* codec can export data for HW decoding (XvMC) */
#define CODEC_CAP_HWACCEL 0x0010 #define CODEC_CAP_HWACCEL 0x0010
/** codec has a non zero delay and needs to be feeded with NULL at the end to get the delayed data */
#define CODEC_CAP_DELAY 0x0020
//the following defines might change, so dont expect compatibility if u use them //the following defines might change, so dont expect compatibility if u use them
#define MB_TYPE_INTRA4x4 0x0001 #define MB_TYPE_INTRA4x4 0x0001
......
...@@ -136,7 +136,9 @@ int MP3lame_encode_frame(AVCodecContext *avctx, ...@@ -136,7 +136,9 @@ int MP3lame_encode_frame(AVCodecContext *avctx,
int lame_result; int lame_result;
/* lame 3.91 dies on '1-channel interleaved' data */ /* lame 3.91 dies on '1-channel interleaved' data */
if (s->stereo) {
if(data){
if (s->stereo) {
lame_result = lame_encode_buffer_interleaved( lame_result = lame_encode_buffer_interleaved(
s->gfp, s->gfp,
data, data,
...@@ -144,7 +146,7 @@ int MP3lame_encode_frame(AVCodecContext *avctx, ...@@ -144,7 +146,7 @@ int MP3lame_encode_frame(AVCodecContext *avctx,
s->buffer + s->buffer_index, s->buffer + s->buffer_index,
BUFFER_SIZE - s->buffer_index BUFFER_SIZE - s->buffer_index
); );
} else { } else {
lame_result = lame_encode_buffer( lame_result = lame_encode_buffer(
s->gfp, s->gfp,
data, data,
...@@ -153,6 +155,13 @@ int MP3lame_encode_frame(AVCodecContext *avctx, ...@@ -153,6 +155,13 @@ int MP3lame_encode_frame(AVCodecContext *avctx,
s->buffer + s->buffer_index, s->buffer + s->buffer_index,
BUFFER_SIZE - s->buffer_index BUFFER_SIZE - s->buffer_index
); );
}
}else{
lame_result= lame_encode_flush(
s->gfp,
s->buffer + s->buffer_index,
BUFFER_SIZE - s->buffer_index
);
} }
if(lame_result==-1) { if(lame_result==-1) {
...@@ -174,7 +183,6 @@ int MP3lame_encode_frame(AVCodecContext *avctx, ...@@ -174,7 +183,6 @@ int MP3lame_encode_frame(AVCodecContext *avctx,
memmove(s->buffer, s->buffer+len, s->buffer_index); memmove(s->buffer, s->buffer+len, s->buffer_index);
//FIXME fix the audio codec API, so we dont need the memcpy() //FIXME fix the audio codec API, so we dont need the memcpy()
//FIXME fix the audio codec API, so we can output multiple packets if we have them
/*for(i=0; i<len; i++){ /*for(i=0; i<len; i++){
av_log(avctx, AV_LOG_DEBUG, "%2X ", frame[i]); av_log(avctx, AV_LOG_DEBUG, "%2X ", frame[i]);
}*/ }*/
...@@ -201,5 +209,6 @@ AVCodec mp3lame_encoder = { ...@@ -201,5 +209,6 @@ AVCodec mp3lame_encoder = {
sizeof(Mp3AudioContext), sizeof(Mp3AudioContext),
MP3lame_encode_init, MP3lame_encode_init,
MP3lame_encode_frame, MP3lame_encode_frame,
MP3lame_encode_close MP3lame_encode_close,
.capabilities= CODEC_CAP_DELAY,
}; };
...@@ -21,7 +21,6 @@ typedef struct OggVorbisContext { ...@@ -21,7 +21,6 @@ typedef struct OggVorbisContext {
vorbis_block vb ; vorbis_block vb ;
uint8_t buffer[BUFFER_SIZE]; uint8_t buffer[BUFFER_SIZE];
int buffer_index; int buffer_index;
int64_t fake_pts; //pts which libavformat will guess, HACK FIXME
/* decoder */ /* decoder */
vorbis_comment vc ; vorbis_comment vc ;
...@@ -104,7 +103,7 @@ static int oggvorbis_encode_frame(AVCodecContext *avccontext, ...@@ -104,7 +103,7 @@ static int oggvorbis_encode_frame(AVCodecContext *avccontext,
float **buffer ; float **buffer ;
ogg_packet op ; ogg_packet op ;
signed char *audio = data ; signed char *audio = data ;
int l, samples = OGGVORBIS_FRAME_SIZE ; int l, samples = data ? OGGVORBIS_FRAME_SIZE : 0;
buffer = vorbis_analysis_buffer(&context->vd, samples) ; buffer = vorbis_analysis_buffer(&context->vd, samples) ;
...@@ -125,6 +124,8 @@ static int oggvorbis_encode_frame(AVCodecContext *avccontext, ...@@ -125,6 +124,8 @@ static int oggvorbis_encode_frame(AVCodecContext *avccontext,
vorbis_bitrate_addblock(&context->vb) ; vorbis_bitrate_addblock(&context->vb) ;
while(vorbis_bitrate_flushpacket(&context->vd, &op)) { while(vorbis_bitrate_flushpacket(&context->vd, &op)) {
if(op.bytes==1) //id love to say this is a hack, bad sadly its not, appearently the end of stream decission is in libogg
continue;
memcpy(context->buffer + context->buffer_index, &op, sizeof(ogg_packet)); memcpy(context->buffer + context->buffer_index, &op, sizeof(ogg_packet));
context->buffer_index += sizeof(ogg_packet); context->buffer_index += sizeof(ogg_packet);
memcpy(context->buffer + context->buffer_index, op.packet, op.bytes); memcpy(context->buffer + context->buffer_index, op.packet, op.bytes);
...@@ -138,21 +139,15 @@ static int oggvorbis_encode_frame(AVCodecContext *avccontext, ...@@ -138,21 +139,15 @@ static int oggvorbis_encode_frame(AVCodecContext *avccontext,
ogg_packet *op2= (ogg_packet*)context->buffer; ogg_packet *op2= (ogg_packet*)context->buffer;
op2->packet = context->buffer + sizeof(ogg_packet); op2->packet = context->buffer + sizeof(ogg_packet);
if(op2->granulepos <= context->fake_pts /*&& (context->fake_pts || context->buffer_index > 4*1024)*/){ l= op2->bytes;
assert(op2->granulepos == context->fake_pts); avccontext->coded_frame->pts= av_rescale(op2->granulepos, AV_TIME_BASE, avccontext->sample_rate);
l= op2->bytes;
memcpy(packets, op2->packet, l); memcpy(packets, op2->packet, l);
context->buffer_index -= l + sizeof(ogg_packet); context->buffer_index -= l + sizeof(ogg_packet);
memcpy(context->buffer, context->buffer + l + sizeof(ogg_packet), context->buffer_index); memcpy(context->buffer, context->buffer + l + sizeof(ogg_packet), context->buffer_index);
}
// av_log(avccontext, AV_LOG_DEBUG, "E%d\n", l); // av_log(avccontext, AV_LOG_DEBUG, "E%d\n", l);
} }
if(l || context->fake_pts){
context->fake_pts += avccontext->frame_size;
}
return l; return l;
} }
...@@ -163,19 +158,6 @@ static int oggvorbis_encode_close(AVCodecContext *avccontext) { ...@@ -163,19 +158,6 @@ static int oggvorbis_encode_close(AVCodecContext *avccontext) {
vorbis_analysis_wrote(&context->vd, 0) ; /* notify vorbisenc this is EOF */ vorbis_analysis_wrote(&context->vd, 0) ; /* notify vorbisenc this is EOF */
/* We need to write all the remaining packets into the stream
* on closing */
av_log(avccontext, AV_LOG_ERROR, "fixme: not all packets written on oggvorbis_encode_close()\n") ;
/*
while(vorbis_bitrate_flushpacket(&context->vd, &op)) {
memcpy(packets + l, &op, sizeof(ogg_packet)) ;
memcpy(packets + l + sizeof(ogg_packet), op.packet, op.bytes) ;
l += sizeof(ogg_packet) + op.bytes ;
}
*/
vorbis_block_clear(&context->vb); vorbis_block_clear(&context->vb);
vorbis_dsp_clear(&context->vd); vorbis_dsp_clear(&context->vd);
vorbis_info_clear(&context->vi); vorbis_info_clear(&context->vi);
...@@ -194,7 +176,8 @@ AVCodec oggvorbis_encoder = { ...@@ -194,7 +176,8 @@ AVCodec oggvorbis_encoder = {
sizeof(OggVorbisContext), sizeof(OggVorbisContext),
oggvorbis_encode_init, oggvorbis_encode_init,
oggvorbis_encode_frame, oggvorbis_encode_frame,
oggvorbis_encode_close oggvorbis_encode_close,
.capabilities= CODEC_CAP_DELAY,
} ; } ;
...@@ -313,4 +296,5 @@ AVCodec oggvorbis_decoder = { ...@@ -313,4 +296,5 @@ AVCodec oggvorbis_decoder = {
NULL, NULL,
oggvorbis_decode_close, oggvorbis_decode_close,
oggvorbis_decode_frame, oggvorbis_decode_frame,
.capabilities= CODEC_CAP_DELAY,
} ; } ;
...@@ -453,24 +453,25 @@ int avcodec_open(AVCodecContext *avctx, AVCodec *codec) ...@@ -453,24 +453,25 @@ int avcodec_open(AVCodecContext *avctx, AVCodec *codec)
int avcodec_encode_audio(AVCodecContext *avctx, uint8_t *buf, int buf_size, int avcodec_encode_audio(AVCodecContext *avctx, uint8_t *buf, int buf_size,
const short *samples) const short *samples)
{ {
int ret; if((avctx->codec->capabilities & CODEC_CAP_DELAY) || samples){
int ret = avctx->codec->encode(avctx, buf, buf_size, (void *)samples);
ret = avctx->codec->encode(avctx, buf, buf_size, (void *)samples); avctx->frame_number++;
avctx->frame_number++; return ret;
return ret; }else
return 0;
} }
int avcodec_encode_video(AVCodecContext *avctx, uint8_t *buf, int buf_size, int avcodec_encode_video(AVCodecContext *avctx, uint8_t *buf, int buf_size,
const AVFrame *pict) const AVFrame *pict)
{ {
int ret; if((avctx->codec->capabilities & CODEC_CAP_DELAY) || pict){
int ret = avctx->codec->encode(avctx, buf, buf_size, (void *)pict);
ret = avctx->codec->encode(avctx, buf, buf_size, (void *)pict); avctx->frame_number++;
emms_c(); //needed to avoid a emms_c() call before every return;
emms_c(); //needed to avoid a emms_c() call before every return; return ret;
}else
avctx->frame_number++; return 0;
return ret;
} }
/** /**
......
...@@ -1980,6 +1980,10 @@ int av_interleaved_write_frame(AVFormatContext *s, AVPacket *pkt){ ...@@ -1980,6 +1980,10 @@ int av_interleaved_write_frame(AVFormatContext *s, AVPacket *pkt){
AVStream *st= s->streams[ pkt->stream_index]; AVStream *st= s->streams[ pkt->stream_index];
compute_pkt_fields2(st, pkt); compute_pkt_fields2(st, pkt);
//FIXME/XXX/HACK drop zero sized packets
if(st->codec.codec_type == CODEC_TYPE_AUDIO && pkt->size==0)
return 0;
if(pkt->dts == AV_NOPTS_VALUE) if(pkt->dts == AV_NOPTS_VALUE)
return -1; return -1;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment