* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-/*!
- * \file libtheoraenc.c
- * \brief Theora encoder using libtheora.
- * \author Paul Richards <paul.richards@gmail.com>
+/**
+ * @file
+ * @brief Theora encoder using libtheora.
+ * @author Paul Richards <paul.richards@gmail.com>
*
* A lot of this is copy / paste from other output codecs in
* libavcodec or pure guesswork (or both).
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)
static int get_stats(AVCodecContext *avctx, int eos)
{
+#ifdef TH_ENCCTL_2PASS_OUT
TheoraContext *h = avctx->priv_data;
uint8_t *buf;
int bytes;
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);
av_base64_encode(avctx->stats_out, b64_size, h->stats, h->stats_offset);
}
return 0;
+#else
+ av_log(avctx, AV_LOG_ERROR, "libtheora too old to support 2pass\n");
+ return -1;
+#endif
}
// libtheora won't read the entire buffer we give it at once, so we have to
// repeatedly submit it...
static int submit_stats(AVCodecContext *avctx)
{
+#ifdef TH_ENCCTL_2PASS_IN
TheoraContext *h = avctx->priv_data;
int bytes;
if (!h->stats) {
h->stats_offset += bytes;
}
return 0;
+#else
+ av_log(avctx, AV_LOG_ERROR, "libtheora too old to support 2pass\n");
+ return -1;
+#endif
}
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);
}
memcpy(outbuf, o_packet.packet, o_packet.bytes);
- // HACK: does not take codec delay into account (neither does the decoder though)
+ // HACK: assumes no encoder delay, this is true until libtheora becomes
+ // multithreaded (which will be disabled unless explictly requested)
avc_context->coded_frame->pts = frame->pts;
+ avc_context->coded_frame->key_frame = !(o_packet.granulepos & h->keyframe_mask);
return o_packet.bytes;
}
return 0;
}
-/*! AVCodec struct exposed to libavcodec */
+/** AVCodec struct exposed to libavcodec */
AVCodec libtheora_encoder = {
.name = "libtheora",
- .type = CODEC_TYPE_VIDEO,
+ .type = AVMEDIA_TYPE_VIDEO,
.id = CODEC_ID_THEORA,
.priv_data_size = sizeof(TheoraContext),
.init = encode_init,