1
0
mirror of https://github.com/mpv-player/mpv synced 2025-01-03 13:32:16 +00:00

encode_lavc: Migrate to codecpar API.

This commit is contained in:
Rudolf Polzer 2016-04-11 14:24:48 -04:00
parent b968d779af
commit 160497b8ff
4 changed files with 274 additions and 231 deletions

View File

@ -42,6 +42,7 @@ struct priv {
uint8_t *buffer; uint8_t *buffer;
size_t buffer_size; size_t buffer_size;
AVStream *stream; AVStream *stream;
AVCodecContext *codec;
int pcmhack; int pcmhack;
int aframesize; int aframesize;
int aframecount; int aframecount;
@ -98,15 +99,14 @@ static int init(struct ao *ao)
pthread_mutex_lock(&ao->encode_lavc_ctx->lock); pthread_mutex_lock(&ao->encode_lavc_ctx->lock);
ac->stream = encode_lavc_alloc_stream(ao->encode_lavc_ctx, if (encode_lavc_alloc_stream(ao->encode_lavc_ctx,
AVMEDIA_TYPE_AUDIO); AVMEDIA_TYPE_AUDIO,
&ac->stream, &ac->codec) < 0) {
if (!ac->stream) { MP_ERR(ao, "could not get a new audio stream\n");
MP_ERR(ao, "could not get a new audio stream\n"); goto fail;
goto fail;
} }
codec = encode_lavc_get_codec(ao->encode_lavc_ctx, ac->stream); codec = ao->encode_lavc_ctx->ac;
int samplerate = af_select_best_samplerate(ao->samplerate, int samplerate = af_select_best_samplerate(ao->samplerate,
codec->supported_samplerates); codec->supported_samplerates);
@ -118,40 +118,40 @@ static int init(struct ao *ao)
// Using codec->time_bvase is deprecated, but needed for older lavf. // Using codec->time_bvase is deprecated, but needed for older lavf.
ac->stream->time_base.num = 1; ac->stream->time_base.num = 1;
ac->stream->time_base.den = ao->samplerate; ac->stream->time_base.den = ao->samplerate;
ac->stream->codec->time_base.num = 1; ac->codec->time_base.num = 1;
ac->stream->codec->time_base.den = ao->samplerate; ac->codec->time_base.den = ao->samplerate;
ac->stream->codec->sample_rate = ao->samplerate; ac->codec->sample_rate = ao->samplerate;
struct mp_chmap_sel sel = {0}; struct mp_chmap_sel sel = {0};
mp_chmap_sel_add_any(&sel); mp_chmap_sel_add_any(&sel);
if (!ao_chmap_sel_adjust(ao, &sel, &ao->channels)) if (!ao_chmap_sel_adjust(ao, &sel, &ao->channels))
goto fail; goto fail;
mp_chmap_reorder_to_lavc(&ao->channels); mp_chmap_reorder_to_lavc(&ao->channels);
ac->stream->codec->channels = ao->channels.num; ac->codec->channels = ao->channels.num;
ac->stream->codec->channel_layout = mp_chmap_to_lavc(&ao->channels); ac->codec->channel_layout = mp_chmap_to_lavc(&ao->channels);
ac->stream->codec->sample_fmt = AV_SAMPLE_FMT_NONE; ac->codec->sample_fmt = AV_SAMPLE_FMT_NONE;
select_format(ao, codec); select_format(ao, codec);
ac->sample_size = af_fmt_to_bytes(ao->format); ac->sample_size = af_fmt_to_bytes(ao->format);
ac->stream->codec->sample_fmt = af_to_avformat(ao->format); ac->codec->sample_fmt = af_to_avformat(ao->format);
ac->stream->codec->bits_per_raw_sample = ac->sample_size * 8; ac->codec->bits_per_raw_sample = ac->sample_size * 8;
if (encode_lavc_open_codec(ao->encode_lavc_ctx, ac->stream) < 0) if (encode_lavc_open_codec(ao->encode_lavc_ctx, ac->codec) < 0)
goto fail; goto fail;
ac->pcmhack = 0; ac->pcmhack = 0;
if (ac->stream->codec->frame_size <= 1) if (ac->codec->frame_size <= 1)
ac->pcmhack = av_get_bits_per_sample(ac->stream->codec->codec_id) / 8; ac->pcmhack = av_get_bits_per_sample(ac->codec->codec_id) / 8;
if (ac->pcmhack) { if (ac->pcmhack) {
ac->aframesize = 16384; // "enough" ac->aframesize = 16384; // "enough"
ac->buffer_size = ac->buffer_size =
ac->aframesize * ac->pcmhack * ao->channels.num * 2 + 200; ac->aframesize * ac->pcmhack * ao->channels.num * 2 + 200;
} else { } else {
ac->aframesize = ac->stream->codec->frame_size; ac->aframesize = ac->codec->frame_size;
ac->buffer_size = ac->buffer_size =
ac->aframesize * ac->sample_size * ao->channels.num * 2 + 200; ac->aframesize * ac->sample_size * ao->channels.num * 2 + 200;
} }
@ -203,7 +203,7 @@ static void uninit(struct ao *ao)
double outpts = ac->expected_next_pts; double outpts = ac->expected_next_pts;
if (!ectx->options->rawts && ectx->options->copyts) if (!ectx->options->rawts && ectx->options->copyts)
outpts += ectx->discontinuity_pts_offset; outpts += ectx->discontinuity_pts_offset;
outpts += encode_lavc_getoffset(ectx, ac->stream); outpts += encode_lavc_getoffset(ectx, ac->codec);
while (encode(ao, outpts, NULL) > 0) ; while (encode(ao, outpts, NULL) > 0) ;
} }
@ -252,25 +252,25 @@ static int encode(struct ao *ao, double apts, void **data)
if (ectx->options->rawts || ectx->options->copyts) { if (ectx->options->rawts || ectx->options->copyts) {
// real audio pts // real audio pts
frame->pts = floor(apts * ac->stream->codec->time_base.den / ac->stream->codec->time_base.num + 0.5); frame->pts = floor(apts * ac->codec->time_base.den / ac->codec->time_base.num + 0.5);
} else { } else {
// audio playback time // audio playback time
frame->pts = floor(realapts * ac->stream->codec->time_base.den / ac->stream->codec->time_base.num + 0.5); frame->pts = floor(realapts * ac->codec->time_base.den / ac->codec->time_base.num + 0.5);
} }
int64_t frame_pts = av_rescale_q(frame->pts, ac->stream->codec->time_base, ac->worst_time_base); int64_t frame_pts = av_rescale_q(frame->pts, ac->codec->time_base, ac->worst_time_base);
if (ac->lastpts != AV_NOPTS_VALUE && frame_pts <= ac->lastpts) { if (ac->lastpts != AV_NOPTS_VALUE && frame_pts <= ac->lastpts) {
// this indicates broken video // this indicates broken video
// (video pts failing to increase fast enough to match audio) // (video pts failing to increase fast enough to match audio)
MP_WARN(ao, "audio frame pts went backwards (%d <- %d), autofixed\n", MP_WARN(ao, "audio frame pts went backwards (%d <- %d), autofixed\n",
(int)frame->pts, (int)ac->lastpts); (int)frame->pts, (int)ac->lastpts);
frame_pts = ac->lastpts + 1; frame_pts = ac->lastpts + 1;
frame->pts = av_rescale_q(frame_pts, ac->worst_time_base, ac->stream->codec->time_base); frame->pts = av_rescale_q(frame_pts, ac->worst_time_base, ac->codec->time_base);
} }
ac->lastpts = frame_pts; ac->lastpts = frame_pts;
frame->quality = ac->stream->codec->global_quality; frame->quality = ac->codec->global_quality;
status = avcodec_encode_audio2(ac->stream->codec, &packet, frame, &gotpacket); status = avcodec_encode_audio2(ac->codec, &packet, frame, &gotpacket);
if (!status) { if (!status) {
if (ac->savepts == AV_NOPTS_VALUE) if (ac->savepts == AV_NOPTS_VALUE)
@ -281,7 +281,7 @@ static int encode(struct ao *ao, double apts, void **data)
} }
else else
{ {
status = avcodec_encode_audio2(ac->stream->codec, &packet, NULL, &gotpacket); status = avcodec_encode_audio2(ac->codec, &packet, NULL, &gotpacket);
} }
if(status) { if(status) {
@ -295,7 +295,7 @@ static int encode(struct ao *ao, double apts, void **data)
MP_DBG(ao, "got pts %f (playback time: %f); out size: %d\n", MP_DBG(ao, "got pts %f (playback time: %f); out size: %d\n",
apts, realapts, packet.size); apts, realapts, packet.size);
encode_lavc_write_stats(ao->encode_lavc_ctx, ac->stream); encode_lavc_write_stats(ao->encode_lavc_ctx, ac->codec);
packet.stream_index = ac->stream->index; packet.stream_index = ac->stream->index;
@ -307,20 +307,20 @@ static int encode(struct ao *ao, double apts, void **data)
} }
if (packet.pts != AV_NOPTS_VALUE) if (packet.pts != AV_NOPTS_VALUE)
packet.pts = av_rescale_q(packet.pts, ac->stream->codec->time_base, packet.pts = av_rescale_q(packet.pts, ac->codec->time_base,
ac->stream->time_base); ac->stream->time_base);
if (packet.dts != AV_NOPTS_VALUE) if (packet.dts != AV_NOPTS_VALUE)
packet.dts = av_rescale_q(packet.dts, ac->stream->codec->time_base, packet.dts = av_rescale_q(packet.dts, ac->codec->time_base,
ac->stream->time_base); ac->stream->time_base);
if(packet.duration > 0) if(packet.duration > 0)
packet.duration = av_rescale_q(packet.duration, ac->stream->codec->time_base, packet.duration = av_rescale_q(packet.duration, ac->codec->time_base,
ac->stream->time_base); ac->stream->time_base);
ac->savepts = AV_NOPTS_VALUE; ac->savepts = AV_NOPTS_VALUE;
if (encode_lavc_write_frame(ao->encode_lavc_ctx, &packet) < 0) { if (encode_lavc_write_frame(ao->encode_lavc_ctx, ac->stream, &packet) < 0) {
MP_ERR(ao, "error writing at %f %f/%f\n", MP_ERR(ao, "error writing at %f %f/%f\n",
realapts, (double) ac->stream->time_base.num, realapts, (double) ac->stream->time_base.num,
(double) ac->stream->time_base.den); (double) ac->stream->time_base.den);
@ -377,22 +377,22 @@ static int play(struct ao *ao, void **data, int samples, int flags)
} }
if (ac->worst_time_base.den == 0) { if (ac->worst_time_base.den == 0) {
//if (ac->stream->codec->time_base.num / ac->stream->codec->time_base.den >= ac->stream->time_base.num / ac->stream->time_base.den) //if (ac->codec->time_base.num / ac->codec->time_base.den >= ac->stream->time_base.num / ac->stream->time_base.den)
if (ac->stream->codec->time_base.num * (double) ac->stream->time_base.den >= if (ac->codec->time_base.num * (double) ac->stream->time_base.den >=
ac->stream->time_base.num * (double) ac->stream->codec->time_base.den) { ac->stream->time_base.num * (double) ac->codec->time_base.den) {
MP_VERBOSE(ao, "NOTE: using codec time base (%d/%d) for pts " MP_VERBOSE(ao, "NOTE: using codec time base (%d/%d) for pts "
"adjustment; the stream base (%d/%d) is not worse.\n", "adjustment; the stream base (%d/%d) is not worse.\n",
(int)ac->stream->codec->time_base.num, (int)ac->codec->time_base.num,
(int)ac->stream->codec->time_base.den, (int)ac->codec->time_base.den,
(int)ac->stream->time_base.num, (int)ac->stream->time_base.num,
(int)ac->stream->time_base.den); (int)ac->stream->time_base.den);
ac->worst_time_base = ac->stream->codec->time_base; ac->worst_time_base = ac->codec->time_base;
ac->worst_time_base_is_stream = 0; ac->worst_time_base_is_stream = 0;
} else { } else {
MP_WARN(ao, "NOTE: not using codec time base (%d/%d) for pts " MP_WARN(ao, "NOTE: not using codec time base (%d/%d) for pts "
"adjustment; the stream base (%d/%d) is worse.\n", "adjustment; the stream base (%d/%d) is worse.\n",
(int)ac->stream->codec->time_base.num, (int)ac->codec->time_base.num,
(int)ac->stream->codec->time_base.den, (int)ac->codec->time_base.den,
(int)ac->stream->time_base.num, (int)ac->stream->time_base.num,
(int)ac->stream->time_base.den); (int)ac->stream->time_base.den);
ac->worst_time_base = ac->stream->time_base; ac->worst_time_base = ac->stream->time_base;
@ -437,7 +437,7 @@ static int play(struct ao *ao, void **data, int samples, int flags)
} }
// Shift pts by the pts offset first. // Shift pts by the pts offset first.
outpts += encode_lavc_getoffset(ectx, ac->stream); outpts += encode_lavc_getoffset(ectx, ac->codec);
while (samples - bufpos >= ac->aframesize) { while (samples - bufpos >= ac->aframesize) {
void *start[MP_NUM_CHANNELS] = {0}; void *start[MP_NUM_CHANNELS] = {0};

View File

@ -21,6 +21,7 @@
#include <libavutil/avutil.h> #include <libavutil/avutil.h>
#include "config.h"
#include "encode_lavc.h" #include "encode_lavc.h"
#include "common/global.h" #include "common/global.h"
#include "common/msg.h" #include "common/msg.h"
@ -291,32 +292,20 @@ int encode_lavc_start(struct encode_lavc_context *ctx)
CHECK_FAIL(ctx, 0); CHECK_FAIL(ctx, 0);
if (ctx->expect_video) { if (ctx->expect_video && ctx->vcc == NULL) {
unsigned i; if (ctx->avc->oformat->video_codec != AV_CODEC_ID_NONE ||
for (i = 0; i < ctx->avc->nb_streams; ++i) ctx->options->vcodec) {
if (ctx->avc->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) encode_lavc_fail(ctx,
break; "no video stream succeeded - invalid codec?\n");
if (i >= ctx->avc->nb_streams) { return 0;
if (ctx->avc->oformat->video_codec != AV_CODEC_ID_NONE ||
ctx->options->vcodec) {
encode_lavc_fail(ctx,
"no video stream succeeded - invalid codec?\n");
return 0;
}
} }
} }
if (ctx->expect_audio) { if (ctx->expect_audio && ctx->acc == NULL) {
unsigned i; if (ctx->avc->oformat->audio_codec != AV_CODEC_ID_NONE ||
for (i = 0; i < ctx->avc->nb_streams; ++i) ctx->options->acodec) {
if (ctx->avc->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO) encode_lavc_fail(ctx,
break; "no audio stream succeeded - invalid codec?\n");
if (i >= ctx->avc->nb_streams) { return 0;
if (ctx->avc->oformat->audio_codec != AV_CODEC_ID_NONE ||
ctx->options->acodec) {
encode_lavc_fail(ctx,
"no audio stream succeeded - invalid codec?\n");
return 0;
}
} }
} }
@ -387,33 +376,38 @@ void encode_lavc_finish(struct encode_lavc_context *ctx)
if (ctx->header_written > 0) if (ctx->header_written > 0)
av_write_trailer(ctx->avc); // this is allowed to fail av_write_trailer(ctx->avc); // this is allowed to fail
for (i = 0; i < ctx->avc->nb_streams; i++) { if (ctx->vcc) {
switch (ctx->avc->streams[i]->codec->codec_type) { if (ctx->twopass_bytebuffer_v) {
case AVMEDIA_TYPE_VIDEO: char *stats = ctx->vcc->stats_out;
if (ctx->twopass_bytebuffer_v) { if (stats)
char *stats = ctx->avc->streams[i]->codec->stats_out; stream_write_buffer(ctx->twopass_bytebuffer_v,
if (stats) stats, strlen(stats));
stream_write_buffer(ctx->twopass_bytebuffer_v,
stats, strlen(stats));
}
break;
case AVMEDIA_TYPE_AUDIO:
if (ctx->twopass_bytebuffer_a) {
char *stats = ctx->avc->streams[i]->codec->stats_out;
if (stats)
stream_write_buffer(ctx->twopass_bytebuffer_a,
stats, strlen(stats));
}
break;
default:
break;
} }
avcodec_close(ctx->avc->streams[i]->codec); avcodec_close(ctx->vcc);
talloc_free(ctx->avc->streams[i]->codec->stats_in); talloc_free(ctx->vcc->stats_in);
av_free(ctx->avc->streams[i]->codec); av_free(ctx->vcc);
ctx->vcc = NULL;
}
if (ctx->acc) {
if (ctx->twopass_bytebuffer_a) {
char *stats = ctx->acc->stats_out;
if (stats)
stream_write_buffer(ctx->twopass_bytebuffer_a,
stats, strlen(stats));
}
avcodec_close(ctx->acc);
talloc_free(ctx->acc->stats_in);
av_free(ctx->acc);
ctx->acc = NULL;
}
for (i = 0; i < ctx->avc->nb_streams; i++) {
av_free(ctx->avc->streams[i]->info); av_free(ctx->avc->streams[i]->info);
av_free(ctx->avc->streams[i]); av_free(ctx->avc->streams[i]);
} }
ctx->vst = NULL;
ctx->ast = NULL;
if (ctx->twopass_bytebuffer_v) { if (ctx->twopass_bytebuffer_v) {
free_stream(ctx->twopass_bytebuffer_v); free_stream(ctx->twopass_bytebuffer_v);
@ -437,6 +431,7 @@ void encode_lavc_finish(struct encode_lavc_context *ctx)
} }
av_free(ctx->avc); av_free(ctx->avc);
ctx->avc = NULL;
} }
ctx->finished = true; ctx->finished = true;
@ -461,7 +456,9 @@ void encode_lavc_set_audio_pts(struct encode_lavc_context *ctx, double pts)
static void encode_2pass_prepare(struct encode_lavc_context *ctx, static void encode_2pass_prepare(struct encode_lavc_context *ctx,
AVDictionary **dictp, AVDictionary **dictp,
AVStream *stream, struct stream **bytebuf, AVStream *stream,
AVCodecContext *codec,
struct stream **bytebuf,
const char *prefix) const char *prefix)
{ {
if (!*bytebuf) { if (!*bytebuf) {
@ -476,7 +473,7 @@ static void encode_2pass_prepare(struct encode_lavc_context *ctx,
if (!(*bytebuf = stream_open(buf, ctx->global))) { if (!(*bytebuf = stream_open(buf, ctx->global))) {
MP_WARN(ctx, "%s: could not open '%s', " MP_WARN(ctx, "%s: could not open '%s', "
"disabling 2-pass encoding at pass 2\n", prefix, buf); "disabling 2-pass encoding at pass 2\n", prefix, buf);
stream->codec->flags &= ~CODEC_FLAG_PASS2; codec->flags &= ~CODEC_FLAG_PASS2;
set_to_avdictionary(ctx, dictp, "flags", "-pass2"); set_to_avdictionary(ctx, dictp, "flags", "-pass2");
} else { } else {
struct bstr content = stream_read_complete(*bytebuf, NULL, struct bstr content = stream_read_complete(*bytebuf, NULL,
@ -487,7 +484,7 @@ static void encode_2pass_prepare(struct encode_lavc_context *ctx,
prefix, ctx->avc->filename); prefix, ctx->avc->filename);
} else { } else {
content.start[content.len] = 0; content.start[content.len] = 0;
stream->codec->stats_in = content.start; codec->stats_in = content.start;
} }
free_stream(*bytebuf); free_stream(*bytebuf);
*bytebuf = NULL; *bytebuf = NULL;
@ -506,43 +503,55 @@ static void encode_2pass_prepare(struct encode_lavc_context *ctx,
} }
} }
AVStream *encode_lavc_alloc_stream(struct encode_lavc_context *ctx, int encode_lavc_alloc_stream(struct encode_lavc_context *ctx,
enum AVMediaType mt) enum AVMediaType mt,
AVStream **stream_out,
AVCodecContext **codec_out)
{ {
AVDictionaryEntry *de; AVDictionaryEntry *de;
AVStream *stream = NULL;
char **p; char **p;
int i;
CHECK_FAIL(ctx, NULL); *stream_out = NULL;
*codec_out = NULL;
CHECK_FAIL(ctx, -1);
if (ctx->header_written) if (ctx->header_written)
return NULL; return -1;
for (i = 0; i < ctx->avc->nb_streams; ++i)
if (ctx->avc->streams[i]->codec->codec_type == mt)
// already have a stream of that type, this cannot really happen
return NULL;
if (ctx->avc->nb_streams == 0) { if (ctx->avc->nb_streams == 0) {
// if this stream isn't stream #0, allocate a dummy stream first for // if this stream isn't stream #0, allocate a dummy stream first for
// the next loop to use // the next call to use
if (mt == AVMEDIA_TYPE_VIDEO && ctx->audio_first) { if (mt == AVMEDIA_TYPE_VIDEO && ctx->audio_first) {
MP_INFO(ctx, "vo-lavc: preallocated audio stream for later use\n"); MP_INFO(ctx, "vo-lavc: preallocated audio stream for later use\n");
avformat_new_stream(ctx->avc, NULL); // this one is AVMEDIA_TYPE_UNKNOWN for now ctx->ast = avformat_new_stream(
ctx->avc, NULL); // this one is AVMEDIA_TYPE_UNKNOWN for now
} }
if (mt == AVMEDIA_TYPE_AUDIO && ctx->video_first) { if (mt == AVMEDIA_TYPE_AUDIO && ctx->video_first) {
MP_INFO(ctx, "ao-lavc: preallocated video stream for later use\n"); MP_INFO(ctx, "ao-lavc: preallocated video stream for later use\n");
avformat_new_stream(ctx->avc, NULL); // this one is AVMEDIA_TYPE_UNKNOWN for now ctx->vst = avformat_new_stream(
ctx->avc, NULL); // this one is AVMEDIA_TYPE_UNKNOWN for now
} }
} else {
// find possibly preallocated stream
for (i = 0; i < ctx->avc->nb_streams; ++i)
if (ctx->avc->streams[i]->codec->codec_type == AVMEDIA_TYPE_UNKNOWN) // preallocated stream
stream = ctx->avc->streams[i];
} }
if (!stream)
stream = avformat_new_stream(ctx->avc, NULL); // already have a stream of that type (this cannot really happen)?
switch (mt) {
case AVMEDIA_TYPE_VIDEO:
if (ctx->vcc != NULL)
return -1;
if (ctx->vst == NULL)
ctx->vst = avformat_new_stream(ctx->avc, NULL);
break;
case AVMEDIA_TYPE_AUDIO:
if (ctx->acc != NULL)
return -1;
if (ctx->ast == NULL)
ctx->ast = avformat_new_stream(ctx->avc, NULL);
break;
default:
encode_lavc_fail(ctx, "requested invalid stream type\n");
return -1;
}
if (ctx->timebase.den == 0) { if (ctx->timebase.den == 0) {
AVRational r; AVRational r;
@ -584,13 +593,18 @@ AVStream *encode_lavc_alloc_stream(struct encode_lavc_context *ctx,
ctx->options->vcodec) { ctx->options->vcodec) {
encode_lavc_fail(ctx, "vo-lavc: encoder not found\n"); encode_lavc_fail(ctx, "vo-lavc: encoder not found\n");
} }
return NULL; return -1;
} }
avcodec_get_context_defaults3(stream->codec, ctx->vc); #if HAVE_AVCODEC_HAS_CODECPAR
ctx->vcc = avcodec_alloc_context3(ctx->vc);
#else
avcodec_get_context_defaults3(ctx->vst->codec, ctx->vc);
ctx->vcc = ctx->vst->codec;
#endif
// Using codec->time_base is deprecated, but needed for older lavf. // Using codec->time_base is deprecated, but needed for older lavf.
stream->time_base = ctx->timebase; ctx->vst->time_base = ctx->timebase;
stream->codec->time_base = ctx->timebase; ctx->vcc->time_base = ctx->timebase;
ctx->voptions = NULL; ctx->voptions = NULL;
@ -606,10 +620,12 @@ AVStream *encode_lavc_alloc_stream(struct encode_lavc_context *ctx,
if (ctx->avc->oformat->flags & AVFMT_GLOBALHEADER) if (ctx->avc->oformat->flags & AVFMT_GLOBALHEADER)
set_to_avdictionary(ctx, &ctx->voptions, "flags", "+global_header"); set_to_avdictionary(ctx, &ctx->voptions, "flags", "+global_header");
encode_2pass_prepare(ctx, &ctx->voptions, stream, encode_2pass_prepare(ctx, &ctx->voptions, ctx->vst, ctx->vcc,
&ctx->twopass_bytebuffer_v, &ctx->twopass_bytebuffer_v,
"vo-lavc"); "vo-lavc");
break; *stream_out = ctx->vst;
*codec_out = ctx->vcc;
return 0;
case AVMEDIA_TYPE_AUDIO: case AVMEDIA_TYPE_AUDIO:
if (!ctx->ac) { if (!ctx->ac) {
@ -617,15 +633,20 @@ AVStream *encode_lavc_alloc_stream(struct encode_lavc_context *ctx,
ctx->options->acodec) { ctx->options->acodec) {
encode_lavc_fail(ctx, "ao-lavc: encoder not found\n"); encode_lavc_fail(ctx, "ao-lavc: encoder not found\n");
} }
return NULL; return -1;
} }
avcodec_get_context_defaults3(stream->codec, ctx->ac); #if HAVE_AVCODEC_HAS_CODECPAR
ctx->acc = avcodec_alloc_context3(ctx->ac);
#else
avcodec_get_context_defaults3(ctx->ast->codec, ctx->ac);
ctx->acc = ctx->ast->codec;
#endif
// Using codec->time_base is deprecated, but needed for older lavf. // Using codec->time_base is deprecated, but needed for older lavf.
stream->time_base = ctx->timebase; ctx->ast->time_base = ctx->timebase;
stream->codec->time_base = ctx->timebase; ctx->acc->time_base = ctx->timebase;
ctx->aoptions = NULL; ctx->aoptions = 0;
if (ctx->options->aopts) if (ctx->options->aopts)
for (p = ctx->options->aopts; *p; ++p) for (p = ctx->options->aopts; *p; ++p)
@ -639,49 +660,34 @@ AVStream *encode_lavc_alloc_stream(struct encode_lavc_context *ctx,
if (ctx->avc->oformat->flags & AVFMT_GLOBALHEADER) if (ctx->avc->oformat->flags & AVFMT_GLOBALHEADER)
set_to_avdictionary(ctx, &ctx->aoptions, "flags", "+global_header"); set_to_avdictionary(ctx, &ctx->aoptions, "flags", "+global_header");
encode_2pass_prepare(ctx, &ctx->aoptions, stream, encode_2pass_prepare(ctx, &ctx->aoptions, ctx->ast, ctx->acc,
&ctx->twopass_bytebuffer_a, &ctx->twopass_bytebuffer_a,
"ao-lavc"); "ao-lavc");
break;
default: *stream_out = ctx->ast;
encode_lavc_fail(ctx, "requested invalid stream type\n"); *codec_out = ctx->acc;
return NULL; return 0;
} }
return stream; // Unreachable.
return -1;
} }
AVCodec *encode_lavc_get_codec(struct encode_lavc_context *ctx, int encode_lavc_open_codec(struct encode_lavc_context *ctx,
AVStream *stream) AVCodecContext *codec)
{
CHECK_FAIL(ctx, NULL);
switch (stream->codec->codec_type) {
case AVMEDIA_TYPE_VIDEO:
return ctx->vc;
case AVMEDIA_TYPE_AUDIO:
return ctx->ac;
default:
break;
}
return NULL;
}
int encode_lavc_open_codec(struct encode_lavc_context *ctx, AVStream *stream)
{ {
AVDictionaryEntry *de; AVDictionaryEntry *de;
int ret; int ret;
CHECK_FAIL(ctx, -1); CHECK_FAIL(ctx, -1);
switch (stream->codec->codec_type) { switch (codec->codec_type) {
case AVMEDIA_TYPE_VIDEO: case AVMEDIA_TYPE_VIDEO:
MP_INFO(ctx, "Opening video encoder: %s [%s]\n", MP_INFO(ctx, "Opening video encoder: %s [%s]\n",
ctx->vc->long_name, ctx->vc->name); ctx->vc->long_name, ctx->vc->name);
if (ctx->vc->capabilities & CODEC_CAP_EXPERIMENTAL) { if (ctx->vc->capabilities & CODEC_CAP_EXPERIMENTAL) {
stream->codec->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL; codec->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL;
MP_WARN(ctx, "\n\n" MP_WARN(ctx, "\n\n"
" ********************************************\n" " ********************************************\n"
" **** Experimental VIDEO codec selected! ****\n" " **** Experimental VIDEO codec selected! ****\n"
@ -701,7 +707,11 @@ int encode_lavc_open_codec(struct encode_lavc_context *ctx, AVStream *stream)
ctx->vc->name); ctx->vc->name);
} }
ret = avcodec_open2(stream->codec, ctx->vc, &ctx->voptions); ret = avcodec_open2(codec, ctx->vc, &ctx->voptions);
#if HAVE_AVCODEC_HAS_CODECPAR
if (ret >= 0)
ret = avcodec_parameters_from_context(ctx->vst->codecpar, codec);
#endif
// complain about all remaining options, then free the dict // complain about all remaining options, then free the dict
for (de = NULL; (de = av_dict_get(ctx->voptions, "", de, for (de = NULL; (de = av_dict_get(ctx->voptions, "", de,
@ -716,7 +726,7 @@ int encode_lavc_open_codec(struct encode_lavc_context *ctx, AVStream *stream)
ctx->ac->long_name, ctx->ac->name); ctx->ac->long_name, ctx->ac->name);
if (ctx->ac->capabilities & CODEC_CAP_EXPERIMENTAL) { if (ctx->ac->capabilities & CODEC_CAP_EXPERIMENTAL) {
stream->codec->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL; codec->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL;
MP_WARN(ctx, "\n\n" MP_WARN(ctx, "\n\n"
" ********************************************\n" " ********************************************\n"
" **** Experimental AUDIO codec selected! ****\n" " **** Experimental AUDIO codec selected! ****\n"
@ -735,7 +745,12 @@ int encode_lavc_open_codec(struct encode_lavc_context *ctx, AVStream *stream)
"If none of this helps you, try another codec in place of %s.\n\n", "If none of this helps you, try another codec in place of %s.\n\n",
ctx->ac->name); ctx->ac->name);
} }
ret = avcodec_open2(stream->codec, ctx->ac, &ctx->aoptions);
ret = avcodec_open2(codec, ctx->ac, &ctx->aoptions);
#if HAVE_AVCODEC_HAS_CODECPAR
if (ret >= 0)
ret = avcodec_parameters_from_context(ctx->ast->codecpar, codec);
#endif
// complain about all remaining options, then free the dict // complain about all remaining options, then free the dict
for (de = NULL; (de = av_dict_get(ctx->aoptions, "", de, for (de = NULL; (de = av_dict_get(ctx->aoptions, "", de,
@ -757,36 +772,43 @@ int encode_lavc_open_codec(struct encode_lavc_context *ctx, AVStream *stream)
return ret; return ret;
} }
void encode_lavc_write_stats(struct encode_lavc_context *ctx, AVStream *stream) void encode_lavc_write_stats(struct encode_lavc_context *ctx,
AVCodecContext *codec)
{ {
CHECK_FAIL(ctx, ); CHECK_FAIL(ctx, );
switch (stream->codec->codec_type) { switch (codec->codec_type) {
case AVMEDIA_TYPE_VIDEO: case AVMEDIA_TYPE_VIDEO:
if (ctx->twopass_bytebuffer_v) if (ctx->twopass_bytebuffer_v)
if (stream->codec->stats_out) if (codec->stats_out)
stream_write_buffer(ctx->twopass_bytebuffer_v, stream_write_buffer(ctx->twopass_bytebuffer_v,
stream->codec->stats_out, codec->stats_out,
strlen(stream->codec->stats_out)); strlen(codec->stats_out));
break; break;
case AVMEDIA_TYPE_AUDIO: case AVMEDIA_TYPE_AUDIO:
if (ctx->twopass_bytebuffer_a) if (ctx->twopass_bytebuffer_a)
if (stream->codec->stats_out) if (codec->stats_out)
stream_write_buffer(ctx->twopass_bytebuffer_a, stream_write_buffer(ctx->twopass_bytebuffer_a,
stream->codec->stats_out, codec->stats_out,
strlen(stream->codec->stats_out)); strlen(codec->stats_out));
break; break;
default: default:
break; break;
} }
} }
int encode_lavc_write_frame(struct encode_lavc_context *ctx, AVPacket *packet) int encode_lavc_write_frame(struct encode_lavc_context *ctx, AVStream *stream,
AVPacket *packet)
{ {
int r; int r;
CHECK_FAIL(ctx, -1); CHECK_FAIL(ctx, -1);
if (stream->index != packet->stream_index) {
MP_ERR(ctx, "Called encode_lavc_write_frame on the wrong stream\n");
return -1;
}
if (ctx->header_written <= 0) if (ctx->header_written <= 0)
return -1; return -1;
@ -795,27 +817,32 @@ int encode_lavc_write_frame(struct encode_lavc_context *ctx, AVPacket *packet)
(int)packet->stream_index, (int)packet->stream_index,
(int)packet->pts, (int)packet->pts,
packet->pts packet->pts
* (double)ctx->avc->streams[packet->stream_index]->time_base.num * (double)stream->time_base.num
/ (double)ctx->avc->streams[packet->stream_index]->time_base.den, / (double)stream->time_base.den,
(int)packet->dts, (int)packet->dts,
packet->dts packet->dts
* (double)ctx->avc->streams[packet->stream_index]->time_base.num * (double)stream->time_base.num
/ (double)ctx->avc->streams[packet->stream_index]->time_base.den, / (double)stream->time_base.den,
(int)packet->size); (int)packet->size);
switch (ctx->avc->streams[packet->stream_index]->codec->codec_type) {
case AVMEDIA_TYPE_VIDEO: #if HAVE_AVCODEC_HAS_CODECPAR
ctx->vbytes += packet->size; switch (stream->codecpar->codec_type) {
++ctx->frames; #else
break; switch (stream->codec->codec_type) {
case AVMEDIA_TYPE_AUDIO: #endif
ctx->abytes += packet->size; case AVMEDIA_TYPE_VIDEO:
ctx->audioseconds += packet->duration ctx->vbytes += packet->size;
* (double)ctx->avc->streams[packet->stream_index]->time_base.num ++ctx->frames;
/ (double)ctx->avc->streams[packet->stream_index]->time_base.den; break;
break; case AVMEDIA_TYPE_AUDIO:
default: ctx->abytes += packet->size;
break; ctx->audioseconds += packet->duration
* (double)stream->time_base.num
/ (double)stream->time_base.den;
break;
default:
break;
} }
r = av_interleaved_write_frame(ctx->avc, packet); r = av_interleaved_write_frame(ctx->avc, packet);
@ -1062,11 +1089,12 @@ bool encode_lavc_showhelp(struct mp_log *log, struct encode_opts *opts)
return help_output; return help_output;
} }
double encode_lavc_getoffset(struct encode_lavc_context *ctx, AVStream *stream) double encode_lavc_getoffset(struct encode_lavc_context *ctx,
AVCodecContext *codec)
{ {
CHECK_FAIL(ctx, 0); CHECK_FAIL(ctx, 0);
switch (stream->codec->codec_type) { switch (codec->codec_type) {
case AVMEDIA_TYPE_VIDEO: case AVMEDIA_TYPE_VIDEO:
return ctx->options->voffset; return ctx->options->voffset;
case AVMEDIA_TYPE_AUDIO: case AVMEDIA_TYPE_AUDIO:
@ -1151,49 +1179,49 @@ void encode_lavc_fail(struct encode_lavc_context *ctx, const char *format, ...)
} }
bool encode_lavc_set_csp(struct encode_lavc_context *ctx, bool encode_lavc_set_csp(struct encode_lavc_context *ctx,
AVStream *stream, enum mp_csp csp) AVCodecContext *codec, enum mp_csp csp)
{ {
CHECK_FAIL(ctx, NULL); CHECK_FAIL(ctx, NULL);
if (ctx->header_written) { if (ctx->header_written) {
if (stream->codec->colorspace != mp_csp_to_avcol_spc(csp)) if (codec->colorspace != mp_csp_to_avcol_spc(csp))
MP_WARN(ctx, "can not change color space during encoding\n"); MP_WARN(ctx, "can not change color space during encoding\n");
return false; return false;
} }
stream->codec->colorspace = mp_csp_to_avcol_spc(csp); codec->colorspace = mp_csp_to_avcol_spc(csp);
return true; return true;
} }
bool encode_lavc_set_csp_levels(struct encode_lavc_context *ctx, bool encode_lavc_set_csp_levels(struct encode_lavc_context *ctx,
AVStream *stream, enum mp_csp_levels lev) AVCodecContext *codec, enum mp_csp_levels lev)
{ {
CHECK_FAIL(ctx, NULL); CHECK_FAIL(ctx, NULL);
if (ctx->header_written) { if (ctx->header_written) {
if (stream->codec->color_range != mp_csp_levels_to_avcol_range(lev)) if (codec->color_range != mp_csp_levels_to_avcol_range(lev))
MP_WARN(ctx, "can not change color space during encoding\n"); MP_WARN(ctx, "can not change color space during encoding\n");
return false; return false;
} }
stream->codec->color_range = mp_csp_levels_to_avcol_range(lev); codec->color_range = mp_csp_levels_to_avcol_range(lev);
return true; return true;
} }
enum mp_csp encode_lavc_get_csp(struct encode_lavc_context *ctx, enum mp_csp encode_lavc_get_csp(struct encode_lavc_context *ctx,
AVStream *stream) AVCodecContext *codec)
{ {
CHECK_FAIL(ctx, 0); CHECK_FAIL(ctx, 0);
return avcol_spc_to_mp_csp(stream->codec->colorspace); return avcol_spc_to_mp_csp(codec->colorspace);
} }
enum mp_csp_levels encode_lavc_get_csp_levels(struct encode_lavc_context *ctx, enum mp_csp_levels encode_lavc_get_csp_levels(struct encode_lavc_context *ctx,
AVStream *stream) AVCodecContext *codec)
{ {
CHECK_FAIL(ctx, 0); CHECK_FAIL(ctx, 0);
return avcol_range_to_mp_csp_levels(stream->codec->color_range); return avcol_range_to_mp_csp_levels(codec->color_range);
} }
// vim: ts=4 sw=4 et // vim: ts=4 sw=4 et

View File

@ -46,8 +46,14 @@ struct encode_lavc_context {
float vo_fps; float vo_fps;
// these are processed from the options // FFmpeg contexts.
AVFormatContext *avc; AVFormatContext *avc;
AVStream *vst;
AVStream *ast;
AVCodecContext *vcc;
AVCodecContext *acc;
// these are processed from the options
AVRational timebase; AVRational timebase;
AVCodec *vc; AVCodec *vc;
AVCodec *ac; AVCodec *ac;
@ -88,26 +94,31 @@ struct encode_lavc_context {
}; };
// interface for vo/ao drivers // interface for vo/ao drivers
AVStream *encode_lavc_alloc_stream(struct encode_lavc_context *ctx, enum AVMediaType mt); int encode_lavc_alloc_stream(struct encode_lavc_context *ctx,
void encode_lavc_write_stats(struct encode_lavc_context *ctx, AVStream *stream); enum AVMediaType mt, AVStream **stream_out,
int encode_lavc_write_frame(struct encode_lavc_context *ctx, AVPacket *packet); AVCodecContext **codec_out);
void encode_lavc_write_stats(struct encode_lavc_context *ctx,
AVCodecContext *stream);
int encode_lavc_write_frame(struct encode_lavc_context *ctx, AVStream *stream,
AVPacket *packet);
int encode_lavc_supports_pixfmt(struct encode_lavc_context *ctx, enum AVPixelFormat format); int encode_lavc_supports_pixfmt(struct encode_lavc_context *ctx, enum AVPixelFormat format);
AVCodec *encode_lavc_get_codec(struct encode_lavc_context *ctx, AVStream *stream); int encode_lavc_open_codec(struct encode_lavc_context *ctx,
int encode_lavc_open_codec(struct encode_lavc_context *ctx, AVStream *stream); AVCodecContext *codec);
int encode_lavc_available(struct encode_lavc_context *ctx); int encode_lavc_available(struct encode_lavc_context *ctx);
int encode_lavc_timesyncfailed(struct encode_lavc_context *ctx); int encode_lavc_timesyncfailed(struct encode_lavc_context *ctx);
int encode_lavc_start(struct encode_lavc_context *ctx); // returns 1 on success int encode_lavc_start(struct encode_lavc_context *ctx); // returns 1 on success
int encode_lavc_oformat_flags(struct encode_lavc_context *ctx); int encode_lavc_oformat_flags(struct encode_lavc_context *ctx);
double encode_lavc_getoffset(struct encode_lavc_context *ctx, AVStream *stream); double encode_lavc_getoffset(struct encode_lavc_context *ctx,
AVCodecContext *codec);
void encode_lavc_fail(struct encode_lavc_context *ctx, const char *format, ...); // report failure of encoding void encode_lavc_fail(struct encode_lavc_context *ctx, const char *format, ...); // report failure of encoding
bool encode_lavc_set_csp(struct encode_lavc_context *ctx, bool encode_lavc_set_csp(struct encode_lavc_context *ctx,
AVStream *stream, enum mp_csp csp); AVCodecContext *codec, enum mp_csp csp);
bool encode_lavc_set_csp_levels(struct encode_lavc_context *ctx, bool encode_lavc_set_csp_levels(struct encode_lavc_context *ctx,
AVStream *stream, enum mp_csp_levels lev); AVCodecContext *codec, enum mp_csp_levels lev);
enum mp_csp encode_lavc_get_csp(struct encode_lavc_context *ctx, enum mp_csp encode_lavc_get_csp(struct encode_lavc_context *ctx,
AVStream *stream); AVCodecContext *codec);
enum mp_csp_levels encode_lavc_get_csp_levels(struct encode_lavc_context *ctx, enum mp_csp_levels encode_lavc_get_csp_levels(struct encode_lavc_context *ctx,
AVStream *stream); AVCodecContext *codec);
#endif #endif

View File

@ -37,6 +37,7 @@ struct priv {
uint8_t *buffer; uint8_t *buffer;
size_t buffer_size; size_t buffer_size;
AVStream *stream; AVStream *stream;
AVCodecContext *codec;
int have_first_packet; int have_first_packet;
int harddup; int harddup;
@ -108,14 +109,14 @@ static int reconfig(struct vo *vo, struct mp_image_params *params)
* warning here. We choose to ignore that; just because ffmpeg currently * warning here. We choose to ignore that; just because ffmpeg currently
* uses a plain 'int' for these struct fields, it doesn't mean it always * uses a plain 'int' for these struct fields, it doesn't mean it always
* will */ * will */
if (width == vc->stream->codec->width && if (width == vc->codec->width &&
height == vc->stream->codec->height) { height == vc->codec->height) {
if (aspect.num != vc->stream->codec->sample_aspect_ratio.num || if (aspect.num != vc->codec->sample_aspect_ratio.num ||
aspect.den != vc->stream->codec->sample_aspect_ratio.den) { aspect.den != vc->codec->sample_aspect_ratio.den) {
/* aspect-only changes are not critical */ /* aspect-only changes are not critical */
MP_WARN(vo, "unsupported pixel aspect ratio change from %d:%d to %d:%d\n", MP_WARN(vo, "unsupported pixel aspect ratio change from %d:%d to %d:%d\n",
vc->stream->codec->sample_aspect_ratio.num, vc->codec->sample_aspect_ratio.num,
vc->stream->codec->sample_aspect_ratio.den, vc->codec->sample_aspect_ratio.den,
aspect.num, aspect.den); aspect.num, aspect.den);
} }
goto done; goto done;
@ -144,18 +145,20 @@ static int reconfig(struct vo *vo, struct mp_image_params *params)
goto error; goto error;
} }
vc->stream = encode_lavc_alloc_stream(vo->encode_lavc_ctx, if (encode_lavc_alloc_stream(vo->encode_lavc_ctx,
AVMEDIA_TYPE_VIDEO); AVMEDIA_TYPE_VIDEO,
vc->stream->sample_aspect_ratio = vc->stream->codec->sample_aspect_ratio = &vc->stream, &vc->codec) < 0)
goto error;
vc->stream->sample_aspect_ratio = vc->codec->sample_aspect_ratio =
aspect; aspect;
vc->stream->codec->width = width; vc->codec->width = width;
vc->stream->codec->height = height; vc->codec->height = height;
vc->stream->codec->pix_fmt = pix_fmt; vc->codec->pix_fmt = pix_fmt;
encode_lavc_set_csp(vo->encode_lavc_ctx, vc->stream, params->colorspace); encode_lavc_set_csp(vo->encode_lavc_ctx, vc->codec, params->colorspace);
encode_lavc_set_csp_levels(vo->encode_lavc_ctx, vc->stream, params->colorlevels); encode_lavc_set_csp_levels(vo->encode_lavc_ctx, vc->codec, params->colorlevels);
if (encode_lavc_open_codec(vo->encode_lavc_ctx, vc->stream) < 0) if (encode_lavc_open_codec(vo->encode_lavc_ctx, vc->codec) < 0)
goto error; goto error;
vc->buffer_size = 6 * width * height + 200; vc->buffer_size = 6 * width * height + 200;
@ -204,7 +207,7 @@ static void write_packet(struct vo *vo, int size, AVPacket *packet)
packet->stream_index = vc->stream->index; packet->stream_index = vc->stream->index;
if (packet->pts != AV_NOPTS_VALUE) { if (packet->pts != AV_NOPTS_VALUE) {
packet->pts = av_rescale_q(packet->pts, packet->pts = av_rescale_q(packet->pts,
vc->stream->codec->time_base, vc->codec->time_base,
vc->stream->time_base); vc->stream->time_base);
} else { } else {
MP_VERBOSE(vo, "codec did not provide pts\n"); MP_VERBOSE(vo, "codec did not provide pts\n");
@ -213,12 +216,12 @@ static void write_packet(struct vo *vo, int size, AVPacket *packet)
} }
if (packet->dts != AV_NOPTS_VALUE) { if (packet->dts != AV_NOPTS_VALUE) {
packet->dts = av_rescale_q(packet->dts, packet->dts = av_rescale_q(packet->dts,
vc->stream->codec->time_base, vc->codec->time_base,
vc->stream->time_base); vc->stream->time_base);
} }
if (packet->duration > 0) { if (packet->duration > 0) {
packet->duration = av_rescale_q(packet->duration, packet->duration = av_rescale_q(packet->duration,
vc->stream->codec->time_base, vc->codec->time_base,
vc->stream->time_base); vc->stream->time_base);
} else { } else {
// HACK: libavformat calculates dts wrong if the initial packet // HACK: libavformat calculates dts wrong if the initial packet
@ -226,15 +229,16 @@ static void write_packet(struct vo *vo, int size, AVPacket *packet)
// have b-frames! // have b-frames!
if (!packet->duration) if (!packet->duration)
if (!vc->have_first_packet) if (!vc->have_first_packet)
if (vc->stream->codec->has_b_frames if (vc->codec->has_b_frames
|| vc->stream->codec->max_b_frames) || vc->codec->max_b_frames)
if (vc->stream->time_base.num * 1000LL <= if (vc->stream->time_base.num * 1000LL <=
vc->stream->time_base.den) vc->stream->time_base.den)
packet->duration = FFMAX(1, av_rescale_q(1, packet->duration = FFMAX(1, av_rescale_q(1,
vc->stream->codec->time_base, vc->stream->time_base)); vc->codec->time_base, vc->stream->time_base));
} }
if (encode_lavc_write_frame(vo->encode_lavc_ctx, packet) < 0) { if (encode_lavc_write_frame(vo->encode_lavc_ctx,
vc->stream, packet) < 0) {
MP_ERR(vo, "error writing\n"); MP_ERR(vo, "error writing\n");
return; return;
} }
@ -251,23 +255,23 @@ static int encode_video(struct vo *vo, AVFrame *frame, AVPacket *packet)
return 0; return 0;
memcpy(vc->buffer, frame, sizeof(AVPicture)); memcpy(vc->buffer, frame, sizeof(AVPicture));
MP_DBG(vo, "got pts %f\n", MP_DBG(vo, "got pts %f\n",
frame->pts * (double) vc->stream->codec->time_base.num / frame->pts * (double) vc->codec->time_base.num /
(double) vc->stream->codec->time_base.den); (double) vc->codec->time_base.den);
packet->size = sizeof(AVPicture); packet->size = sizeof(AVPicture);
return packet->size; return packet->size;
} else { } else {
int got_packet = 0; int got_packet = 0;
int status = avcodec_encode_video2(vc->stream->codec, packet, int status = avcodec_encode_video2(vc->codec, packet,
frame, &got_packet); frame, &got_packet);
int size = (status < 0) ? status : got_packet ? packet->size : 0; int size = (status < 0) ? status : got_packet ? packet->size : 0;
if (frame) if (frame)
MP_DBG(vo, "got pts %f; out size: %d\n", MP_DBG(vo, "got pts %f; out size: %d\n",
frame->pts * (double) vc->stream->codec->time_base.num / frame->pts * (double) vc->codec->time_base.num /
(double) vc->stream->codec->time_base.den, size); (double) vc->codec->time_base.den, size);
if (got_packet) if (got_packet)
encode_lavc_write_stats(vo->encode_lavc_ctx, vc->stream); encode_lavc_write_stats(vo->encode_lavc_ctx, vc->codec);
return size; return size;
} }
} }
@ -295,7 +299,7 @@ static void draw_image_unlocked(struct vo *vo, mp_image_t *mpi)
pts = vc->expected_next_pts; pts = vc->expected_next_pts;
} }
avc = vc->stream->codec; avc = vc->codec;
if (vc->worst_time_base.den == 0) { if (vc->worst_time_base.den == 0) {
//if (avc->time_base.num / avc->time_base.den >= vc->stream->time_base.num / vc->stream->time_base.den) //if (avc->time_base.num / avc->time_base.den >= vc->stream->time_base.num / vc->stream->time_base.den)
@ -376,7 +380,7 @@ static void draw_image_unlocked(struct vo *vo, mp_image_t *mpi)
} }
vc->lastpts = outpts; vc->lastpts = outpts;
ectx->last_video_in_pts = pts; ectx->last_video_in_pts = pts;
frameipts = floor((outpts + encode_lavc_getoffset(ectx, vc->stream)) frameipts = floor((outpts + encode_lavc_getoffset(ectx, vc->codec))
/ timeunit + 0.5); / timeunit + 0.5);
// calculate expected pts of next video frame // calculate expected pts of next video frame
@ -396,7 +400,7 @@ static void draw_image_unlocked(struct vo *vo, mp_image_t *mpi)
MP_INFO(vo, "--oneverdrop increased pts by %d\n", MP_INFO(vo, "--oneverdrop increased pts by %d\n",
(int) (vc->lastipts - frameipts + step)); (int) (vc->lastipts - frameipts + step));
frameipts = vc->lastipts + step; frameipts = vc->lastipts + step;
vc->lastpts = frameipts * timeunit - encode_lavc_getoffset(ectx, vc->stream); vc->lastpts = frameipts * timeunit - encode_lavc_getoffset(ectx, vc->codec);
} }
} }