X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Flibtheoraenc.c;h=b88566466e3636d6543caf76a63c9986fb11b935;hb=c9ef6b09326a24010bf86d6b0d19cfa42df4d546;hp=fd4a9ec4152dc88d93570b1a8e5d6c7bef1907ba;hpb=800841fd0c6c686c62bdd482e46b6c61b72fa531;p=ffmpeg diff --git a/libavcodec/libtheoraenc.c b/libavcodec/libtheoraenc.c index fd4a9ec4152..b88566466e3 100644 --- a/libavcodec/libtheoraenc.c +++ b/libavcodec/libtheoraenc.c @@ -1,27 +1,27 @@ /* * Copyright (c) 2006 Paul Richards * - * This file is part of FFmpeg. + * This file is part of Libav. * - * FFmpeg is free software; you can redistribute it and/or + * Libav is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * - * FFmpeg is distributed in the hope that it will be useful, + * Libav is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software + * License along with Libav; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -/*! - * \file libtheoraenc.c - * \brief Theora encoder using libtheora. - * \author Paul Richards +/** + * @file + * @brief Theora encoder using libtheora. + * @author Paul Richards * * A lot of this is copy / paste from other output codecs in * libavcodec or pure guesswork (or both). @@ -30,11 +30,14 @@ * and o_ prefixes on variables which are libogg types. */ -/* FFmpeg includes */ +/* Libav includes */ +#include "libavutil/common.h" #include "libavutil/intreadwrite.h" +#include "libavutil/pixdesc.h" #include "libavutil/log.h" #include "libavutil/base64.h" #include "avcodec.h" +#include "internal.h" /* libtheora includes */ #include @@ -46,11 +49,10 @@ typedef struct TheoraContext { int stats_offset; int uv_hshift; int uv_vshift; + int keyframe_mask; } TheoraContext; -/*! - Concatenates an ogg_packet into the extradata. -*/ +/** Concatenate an ogg_packet into the extradata. */ static int concatenate_packet(unsigned int* offset, AVCodecContext* avc_context, const ogg_packet* packet) @@ -102,7 +104,7 @@ static int get_stats(AVCodecContext *avctx, int eos) memcpy(h->stats + h->stats_offset, buf, bytes); h->stats_offset += bytes; } else { - int b64_size = ((h->stats_offset + 2) / 3) * 4 + 1; + int b64_size = AV_BASE64_SIZE(h->stats_offset); // libtheora generates a summary header at the end memcpy(h->stats, buf, bytes); avctx->stats_out = av_malloc(b64_size); @@ -186,17 +188,18 @@ static av_cold int encode_init(AVCodecContext* avc_context) else t_info.colorspace = TH_CS_UNSPECIFIED; - if (avc_context->pix_fmt == PIX_FMT_YUV420P) + if (avc_context->pix_fmt == AV_PIX_FMT_YUV420P) t_info.pixel_fmt = TH_PF_420; - else if (avc_context->pix_fmt == PIX_FMT_YUV422P) + else if (avc_context->pix_fmt == AV_PIX_FMT_YUV422P) t_info.pixel_fmt = TH_PF_422; - else if (avc_context->pix_fmt == PIX_FMT_YUV444P) + else if (avc_context->pix_fmt == AV_PIX_FMT_YUV444P) t_info.pixel_fmt = TH_PF_444; else { av_log(avc_context, AV_LOG_ERROR, "Unsupported pix_fmt\n"); return -1; } - avcodec_get_chroma_sub_sample(avc_context->pix_fmt, &h->uv_hshift, &h->uv_vshift); + av_pix_fmt_get_chroma_sub_sample(avc_context->pix_fmt, + &h->uv_hshift, &h->uv_vshift); if (avc_context->flags & CODEC_FLAG_QSCALE) { /* to be constant with the libvorbis implementation, clip global_quality to 0 - 10 @@ -204,7 +207,7 @@ static av_cold int encode_init(AVCodecContext* avc_context) * 0 <= p <=63 * an int value */ - t_info.quality = av_clip(avc_context->global_quality / (float)FF_QP2LAMBDA, 0, 10) * 6.3; + t_info.quality = av_clipf(avc_context->global_quality / (float)FF_QP2LAMBDA, 0, 10) * 6.3; t_info.target_bitrate = 0; } else { t_info.target_bitrate = avc_context->bit_rate; @@ -218,6 +221,7 @@ static av_cold int encode_init(AVCodecContext* avc_context) return -1; } + h->keyframe_mask = (1 << t_info.keyframe_granule_shift) - 1; /* Clear up theora_info struct */ th_info_clear(&t_info); @@ -241,7 +245,7 @@ static av_cold int encode_init(AVCodecContext* avc_context) header, comment, and tables. Each one is prefixed with a 16bit size, then they - are concatenated together into ffmpeg's extradata. + are concatenated together into libavcodec's extradata. */ offset = 0; @@ -260,14 +264,13 @@ static av_cold int encode_init(AVCodecContext* avc_context) return 0; } -static int encode_frame(AVCodecContext* avc_context, uint8_t *outbuf, - int buf_size, void *data) +static int encode_frame(AVCodecContext* avc_context, AVPacket *pkt, + const AVFrame *frame, int *got_packet) { th_ycbcr_buffer t_yuv_buffer; TheoraContext *h = avc_context->priv_data; - AVFrame *frame = data; ogg_packet o_packet; - int result, i; + int result, i, ret; // EOS, finish and get 1st pass stats if applicable if (!frame) { @@ -328,16 +331,21 @@ static int encode_frame(AVCodecContext* avc_context, uint8_t *outbuf, } /* Copy ogg_packet content out to buffer */ - if (buf_size < o_packet.bytes) { - av_log(avc_context, AV_LOG_ERROR, "encoded frame too large\n"); - return -1; + if ((ret = ff_alloc_packet(pkt, o_packet.bytes)) < 0) { + av_log(avc_context, AV_LOG_ERROR, "Error getting output packet of size %ld.\n", o_packet.bytes); + return ret; } - memcpy(outbuf, o_packet.packet, o_packet.bytes); + memcpy(pkt->data, o_packet.packet, o_packet.bytes); - // HACK: does not take codec delay into account (neither does the decoder though) - avc_context->coded_frame->pts = frame->pts; + // HACK: assumes no encoder delay, this is true until libtheora becomes + // multithreaded (which will be disabled unless explicitly requested) + pkt->pts = pkt->dts = frame->pts; + avc_context->coded_frame->key_frame = !(o_packet.granulepos & h->keyframe_mask); + if (avc_context->coded_frame->key_frame) + pkt->flags |= AV_PKT_FLAG_KEY; + *got_packet = 1; - return o_packet.bytes; + return 0; } static av_cold int encode_close(AVCodecContext* avc_context) @@ -354,16 +362,18 @@ static av_cold int encode_close(AVCodecContext* avc_context) return 0; } -/*! AVCodec struct exposed to libavcodec */ -AVCodec libtheora_encoder = { - .name = "libtheora", - .type = CODEC_TYPE_VIDEO, - .id = CODEC_ID_THEORA, +/** AVCodec struct exposed to libavcodec */ +AVCodec ff_libtheora_encoder = { + .name = "libtheora", + .long_name = NULL_IF_CONFIG_SMALL("libtheora Theora"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_THEORA, .priv_data_size = sizeof(TheoraContext), - .init = encode_init, - .close = encode_close, - .encode = encode_frame, - .capabilities = CODEC_CAP_DELAY, // needed to get the statsfile summary - .pix_fmts= (const enum PixelFormat[]){PIX_FMT_YUV420P, PIX_FMT_YUV422P, PIX_FMT_YUV444P, PIX_FMT_NONE}, - .long_name = NULL_IF_CONFIG_SMALL("libtheora Theora"), + .init = encode_init, + .close = encode_close, + .encode2 = encode_frame, + .capabilities = CODEC_CAP_DELAY, // needed to get the statsfile summary + .pix_fmts = (const enum AVPixelFormat[]){ + AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV444P, AV_PIX_FMT_NONE + }, };