static int oggvorbis_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, const AVFrame *frame, int *got_packet_ptr) { OggVorbisEncContext *s = avctx->priv_data; ogg_packet op; int ret, duration; /* send samples to libvorbis */ if (frame) { const int samples = frame->nb_samples; float **buffer; int c, channels = s->vi.channels; buffer = vorbis_analysis_buffer(&s->vd, samples); for (c = 0; c < channels; c++) { int co = (channels > 8) ? c : ff_vorbis_encoding_channel_layout_offsets[channels - 1][c]; memcpy(buffer[c], frame->extended_data[co], samples * sizeof(*buffer[c])); } if ((ret = vorbis_analysis_wrote(&s->vd, samples)) < 0) { av_log(avctx, AV_LOG_ERROR, "error in vorbis_analysis_wrote()\n"); return vorbis_error_to_averror(ret); } if ((ret = ff_af_queue_add(&s->afq, frame)) < 0) return ret; } else { if (!s->eof) if ((ret = vorbis_analysis_wrote(&s->vd, 0)) < 0) { av_log(avctx, AV_LOG_ERROR, "error in vorbis_analysis_wrote()\n"); return vorbis_error_to_averror(ret); } s->eof = 1; } /* retrieve available packets from libvorbis */ while ((ret = vorbis_analysis_blockout(&s->vd, &s->vb)) == 1) { if ((ret = vorbis_analysis(&s->vb, NULL)) < 0) break; if ((ret = vorbis_bitrate_addblock(&s->vb)) < 0) break; /* add any available packets to the output packet buffer */ while ((ret = vorbis_bitrate_flushpacket(&s->vd, &op)) == 1) { if (av_fifo_space(s->pkt_fifo) < sizeof(ogg_packet) + op.bytes) { av_log(avctx, AV_LOG_ERROR, "packet buffer is too small\n"); return AVERROR_BUG; } av_fifo_generic_write(s->pkt_fifo, &op, sizeof(ogg_packet), NULL); av_fifo_generic_write(s->pkt_fifo, op.packet, op.bytes, NULL); } if (ret < 0) { av_log(avctx, AV_LOG_ERROR, "error getting available packets\n"); break; } } if (ret < 0) { av_log(avctx, AV_LOG_ERROR, "error getting available packets\n"); return vorbis_error_to_averror(ret); } /* check for available packets */ if (av_fifo_size(s->pkt_fifo) < sizeof(ogg_packet)) return 0; av_fifo_generic_read(s->pkt_fifo, &op, sizeof(ogg_packet), NULL); if ((ret = ff_alloc_packet2(avctx, avpkt, op.bytes))) return ret; av_fifo_generic_read(s->pkt_fifo, avpkt->data, op.bytes, NULL); avpkt->pts = ff_samples_to_time_base(avctx, op.granulepos); duration = avpriv_vorbis_parse_frame(&s->vp, avpkt->data, avpkt->size); if (duration > 0) { /* we do not know encoder delay until we get the first packet from * libvorbis, so we have to update the AudioFrameQueue counts */ if (!avctx->delay && s->afq.frames) { avctx->delay = duration; av_assert0(!s->afq.remaining_delay); s->afq.frames->duration += duration; s->afq.frames->pts -= duration; s->afq.remaining_samples += duration; } ff_af_queue_remove(&s->afq, duration, &avpkt->pts, &avpkt->duration); } *got_packet_ptr = 1; return 0; }