1
0
mirror of https://github.com/FFmpeg/FFmpeg.git synced 2024-12-23 12:43:46 +02:00

Merge remote-tracking branch 'qatar/master'

* qatar/master:
  avconv: use different variables for decoded and filtered frame.
  avconv: add support for copying attachments.
  matroskaenc: write attachments.
  matroskadec: export mimetype of attachments as metadata.
  avconv: factorize common code from new_*_stream()
  doc/avconv: expand documentation for some options.
  doc/avconv: document -timelimit.

Conflicts:
	avconv.c
	cmdutils.c
	tests/codec-regression.sh

Merged-by: Michael Niedermayer <michaelni@gmx.at>
This commit is contained in:
Michael Niedermayer 2011-09-28 01:31:38 +02:00
commit 23c1db9b83
7 changed files with 172 additions and 76 deletions

View File

@ -1588,7 +1588,6 @@ static int output_packet(InputStream *ist, int ist_index,
OutputStream *ost; OutputStream *ost;
int ret, i; int ret, i;
int got_output; int got_output;
AVFrame picture;
void *buffer_to_free = NULL; void *buffer_to_free = NULL;
static unsigned int samples_size= 0; static unsigned int samples_size= 0;
AVSubtitle subtitle, *subtitle_to_free; AVSubtitle subtitle, *subtitle_to_free;
@ -1623,6 +1622,7 @@ static int output_packet(InputStream *ist, int ist_index,
while (avpkt.size > 0 || (!pkt && got_output)) { while (avpkt.size > 0 || (!pkt && got_output)) {
uint8_t *data_buf, *decoded_data_buf; uint8_t *data_buf, *decoded_data_buf;
int data_size, decoded_data_size; int data_size, decoded_data_size;
AVFrame *decoded_frame, *filtered_frame;
handle_eof: handle_eof:
ist->pts= ist->next_pts; ist->pts= ist->next_pts;
@ -1632,6 +1632,7 @@ static int output_packet(InputStream *ist, int ist_index,
ist->showed_multi_packet_warning=1; ist->showed_multi_packet_warning=1;
/* decode the packet if needed */ /* decode the packet if needed */
decoded_frame = filtered_frame = NULL;
decoded_data_buf = NULL; /* fail safe */ decoded_data_buf = NULL; /* fail safe */
decoded_data_size= 0; decoded_data_size= 0;
data_buf = avpkt.data; data_buf = avpkt.data;
@ -1668,22 +1669,23 @@ static int output_packet(InputStream *ist, int ist_index,
break;} break;}
case AVMEDIA_TYPE_VIDEO: case AVMEDIA_TYPE_VIDEO:
decoded_data_size = (ist->st->codec->width * ist->st->codec->height * 3) / 2; decoded_data_size = (ist->st->codec->width * ist->st->codec->height * 3) / 2;
/* XXX: allocate picture correctly */ if (!(decoded_frame = avcodec_alloc_frame()))
avcodec_get_frame_defaults(&picture); return AVERROR(ENOMEM);
avpkt.pts = pkt_pts; avpkt.pts = pkt_pts;
avpkt.dts = ist->pts; avpkt.dts = ist->pts;
pkt_pts = AV_NOPTS_VALUE; pkt_pts = AV_NOPTS_VALUE;
ret = avcodec_decode_video2(ist->st->codec, ret = avcodec_decode_video2(ist->st->codec,
&picture, &got_output, &avpkt); decoded_frame, &got_output, &avpkt);
quality = same_quant ? picture.quality : 0; quality = same_quant ? decoded_frame->quality : 0;
if (ret < 0) if (ret < 0)
return ret; goto fail;
if (!got_output) { if (!got_output) {
/* no picture yet */ /* no picture yet */
av_freep(&decoded_frame);
goto discard_packet; goto discard_packet;
} }
ist->next_pts = ist->pts = picture.best_effort_timestamp; ist->next_pts = ist->pts = decoded_frame->best_effort_timestamp;
if (ist->st->codec->time_base.num != 0) { if (ist->st->codec->time_base.num != 0) {
int ticks= ist->st->parser ? ist->st->parser->repeat_pict+1 : ist->st->codec->ticks_per_frame; int ticks= ist->st->parser ? ist->st->parser->repeat_pict+1 : ist->st->codec->ticks_per_frame;
ist->next_pts += ((int64_t)AV_TIME_BASE * ist->next_pts += ((int64_t)AV_TIME_BASE *
@ -1692,7 +1694,7 @@ static int output_packet(InputStream *ist, int ist_index,
} }
avpkt.size = 0; avpkt.size = 0;
buffer_to_free = NULL; buffer_to_free = NULL;
pre_process_video_frame(ist, (AVPicture *)&picture, &buffer_to_free); pre_process_video_frame(ist, (AVPicture *)decoded_frame, &buffer_to_free);
break; break;
case AVMEDIA_TYPE_SUBTITLE: case AVMEDIA_TYPE_SUBTITLE:
ret = avcodec_decode_subtitle2(ist->st->codec, ret = avcodec_decode_subtitle2(ist->st->codec,
@ -1768,11 +1770,15 @@ static int output_packet(InputStream *ist, int ist_index,
#if CONFIG_AVFILTER #if CONFIG_AVFILTER
if (ist->st->codec->codec_type == AVMEDIA_TYPE_VIDEO && if (ist->st->codec->codec_type == AVMEDIA_TYPE_VIDEO &&
ost->input_video_filter) { ost->input_video_filter) {
if (!picture.sample_aspect_ratio.num) if (!decoded_frame->sample_aspect_ratio.num)
picture.sample_aspect_ratio = ist->st->sample_aspect_ratio; decoded_frame->sample_aspect_ratio = ist->st->sample_aspect_ratio;
picture.pts = ist->pts; decoded_frame->pts = ist->pts;
av_vsrc_buffer_add_frame(ost->input_video_filter, &picture, AV_VSRC_BUF_FLAG_OVERWRITE); av_vsrc_buffer_add_frame(ost->input_video_filter, decoded_frame, AV_VSRC_BUF_FLAG_OVERWRITE);
if (!(filtered_frame = avcodec_alloc_frame())) {
ret = AVERROR(ENOMEM);
goto fail;
}
} }
frame_available = ist->st->codec->codec_type != AVMEDIA_TYPE_VIDEO || frame_available = ist->st->codec->codec_type != AVMEDIA_TYPE_VIDEO ||
!ost->output_video_filter || avfilter_poll_frame(ost->output_video_filter->inputs[0]); !ost->output_video_filter || avfilter_poll_frame(ost->output_video_filter->inputs[0]);
@ -1782,10 +1788,12 @@ static int output_packet(InputStream *ist, int ist_index,
if (av_buffersink_get_buffer_ref(ost->output_video_filter, &ost->picref, 0) < 0) if (av_buffersink_get_buffer_ref(ost->output_video_filter, &ost->picref, 0) < 0)
goto cont; goto cont;
if (ost->picref) { if (ost->picref) {
avfilter_fill_frame_from_video_buffer_ref(&picture, ost->picref); avfilter_fill_frame_from_video_buffer_ref(filtered_frame, ost->picref);
ist->pts = av_rescale_q(ost->picref->pts, ist_pts_tb, AV_TIME_BASE_Q); ist->pts = av_rescale_q(ost->picref->pts, ist_pts_tb, AV_TIME_BASE_Q);
} }
} }
#else
filtered_frame = decoded_frame;
#endif #endif
os = output_files[ost->file_index].ctx; os = output_files[ost->file_index].ctx;
@ -1803,8 +1811,8 @@ static int output_packet(InputStream *ist, int ist_index,
if (ost->picref->video && !ost->frame_aspect_ratio) if (ost->picref->video && !ost->frame_aspect_ratio)
ost->st->codec->sample_aspect_ratio = ost->picref->video->sample_aspect_ratio; ost->st->codec->sample_aspect_ratio = ost->picref->video->sample_aspect_ratio;
#endif #endif
do_video_out(os, ost, ist, &picture, &frame_size, do_video_out(os, ost, ist, filtered_frame, &frame_size,
same_quant ? quality : ost->st->codec->global_quality); same_quant ? quality : ost->st->codec->global_quality);
if (vstats_filename && frame_size) if (vstats_filename && frame_size)
do_video_stats(os, ost, frame_size); do_video_stats(os, ost, frame_size);
break; break;
@ -1884,15 +1892,20 @@ static int output_packet(InputStream *ist, int ist_index,
if (ost->picref) if (ost->picref)
avfilter_unref_buffer(ost->picref); avfilter_unref_buffer(ost->picref);
} }
av_freep(&filtered_frame);
#endif #endif
} }
fail:
av_free(buffer_to_free); av_free(buffer_to_free);
/* XXX: allocate the subtitles in the codec ? */ /* XXX: allocate the subtitles in the codec ? */
if (subtitle_to_free) { if (subtitle_to_free) {
avsubtitle_free(subtitle_to_free); avsubtitle_free(subtitle_to_free);
subtitle_to_free = NULL; subtitle_to_free = NULL;
} }
av_freep(&decoded_frame);
if (ret < 0)
return ret;
} }
discard_packet: discard_packet:
@ -2068,6 +2081,7 @@ static int transcode_init(OutputFile *output_files,
codec->height = icodec->height; codec->height = icodec->height;
break; break;
case AVMEDIA_TYPE_DATA: case AVMEDIA_TYPE_DATA:
case AVMEDIA_TYPE_ATTACHMENT:
break; break;
default: default:
abort(); abort();
@ -3097,6 +3111,9 @@ static OutputStream *new_output_stream(OptionsContext *o, AVFormatContext *oc, e
st->codec->global_quality = FF_QP2LAMBDA * qscale; st->codec->global_quality = FF_QP2LAMBDA * qscale;
} }
if (oc->oformat->flags & AVFMT_GLOBALHEADER)
st->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;
ost->sws_flags = av_get_int(sws_opts, "sws_flags", NULL); ost->sws_flags = av_get_int(sws_opts, "sws_flags", NULL);
return ost; return ost;
} }
@ -3128,10 +3145,6 @@ static OutputStream *new_video_stream(OptionsContext *o, AVFormatContext *oc)
st = ost->st; st = ost->st;
video_enc = st->codec; video_enc = st->codec;
if(oc->oformat->flags & AVFMT_GLOBALHEADER) {
video_enc->flags |= CODEC_FLAG_GLOBAL_HEADER;
}
if (!st->stream_copy) { if (!st->stream_copy) {
const char *p = NULL; const char *p = NULL;
char *forced_key_frames = NULL, *frame_rate = NULL, *frame_size = NULL; char *forced_key_frames = NULL, *frame_rate = NULL, *frame_size = NULL;
@ -3249,9 +3262,6 @@ static OutputStream *new_audio_stream(OptionsContext *o, AVFormatContext *oc)
audio_enc = st->codec; audio_enc = st->codec;
audio_enc->codec_type = AVMEDIA_TYPE_AUDIO; audio_enc->codec_type = AVMEDIA_TYPE_AUDIO;
if (oc->oformat->flags & AVFMT_GLOBALHEADER) {
audio_enc->flags |= CODEC_FLAG_GLOBAL_HEADER;
}
if (!st->stream_copy) { if (!st->stream_copy) {
char *sample_fmt = NULL; char *sample_fmt = NULL;
@ -3274,20 +3284,21 @@ static OutputStream *new_data_stream(OptionsContext *o, AVFormatContext *oc)
{ {
AVStream *st; AVStream *st;
OutputStream *ost; OutputStream *ost;
AVCodecContext *data_enc;
ost = new_output_stream(o, oc, AVMEDIA_TYPE_DATA); ost = new_output_stream(o, oc, AVMEDIA_TYPE_DATA);
st = ost->st; st = ost->st;
data_enc = st->codec;
if (!st->stream_copy) { if (!st->stream_copy) {
av_log(NULL, AV_LOG_FATAL, "Data stream encoding not supported yet (only streamcopy)\n"); av_log(NULL, AV_LOG_FATAL, "Data stream encoding not supported yet (only streamcopy)\n");
exit_program(1); exit_program(1);
} }
if (oc->oformat->flags & AVFMT_GLOBALHEADER) { return ost;
data_enc->flags |= CODEC_FLAG_GLOBAL_HEADER; }
}
static OutputStream *new_attachment_stream(OptionsContext *o, AVFormatContext *oc)
{
OutputStream *ost = new_output_stream(o, oc, AVMEDIA_TYPE_ATTACHMENT);
ost->st->stream_copy = 1;
return ost; return ost;
} }
@ -3303,10 +3314,6 @@ static OutputStream *new_subtitle_stream(OptionsContext *o, AVFormatContext *oc)
subtitle_enc->codec_type = AVMEDIA_TYPE_SUBTITLE; subtitle_enc->codec_type = AVMEDIA_TYPE_SUBTITLE;
if (oc->oformat->flags & AVFMT_GLOBALHEADER) {
subtitle_enc->flags |= CODEC_FLAG_GLOBAL_HEADER;
}
return ost; return ost;
} }
@ -3495,6 +3502,7 @@ static void opt_output_file(void *optctx, const char *filename)
case AVMEDIA_TYPE_AUDIO: ost = new_audio_stream(o, oc); break; case AVMEDIA_TYPE_AUDIO: ost = new_audio_stream(o, oc); break;
case AVMEDIA_TYPE_SUBTITLE: ost = new_subtitle_stream(o, oc); break; case AVMEDIA_TYPE_SUBTITLE: ost = new_subtitle_stream(o, oc); break;
case AVMEDIA_TYPE_DATA: ost = new_data_stream(o, oc); break; case AVMEDIA_TYPE_DATA: ost = new_data_stream(o, oc); break;
case AVMEDIA_TYPE_ATTACHMENT: ost = new_attachment_stream(o, oc); break;
default: default:
av_log(NULL, AV_LOG_FATAL, "Cannot map stream #%d.%d - unsupported type.\n", av_log(NULL, AV_LOG_FATAL, "Cannot map stream #%d.%d - unsupported type.\n",
map->file_index, map->stream_index); map->file_index, map->stream_index);

View File

@ -864,7 +864,7 @@ int check_stream_specifier(AVFormatContext *s, AVStream *st, const char *spec)
{ {
if (*spec <= '9' && *spec >= '0') /* opt:index */ if (*spec <= '9' && *spec >= '0') /* opt:index */
return strtol(spec, NULL, 0) == st->index; return strtol(spec, NULL, 0) == st->index;
else if (*spec == 'v' || *spec == 'a' || *spec == 's' || *spec == 'd') { /* opt:[vasd] */ else if (*spec == 'v' || *spec == 'a' || *spec == 's' || *spec == 'd' || *spec == 't') { /* opt:[vasdt] */
enum AVMediaType type; enum AVMediaType type;
switch (*spec++) { switch (*spec++) {
@ -872,6 +872,7 @@ int check_stream_specifier(AVFormatContext *s, AVStream *st, const char *spec)
case 'a': type = AVMEDIA_TYPE_AUDIO; break; case 'a': type = AVMEDIA_TYPE_AUDIO; break;
case 's': type = AVMEDIA_TYPE_SUBTITLE; break; case 's': type = AVMEDIA_TYPE_SUBTITLE; break;
case 'd': type = AVMEDIA_TYPE_DATA; break; case 'd': type = AVMEDIA_TYPE_DATA; break;
case 't': type = AVMEDIA_TYPE_ATTACHMENT; break;
default: abort(); // never reached, silence warning default: abort(); // never reached, silence warning
} }
if (type != st->codec->codec_type) if (type != st->codec->codec_type)

View File

@ -82,13 +82,15 @@ described.
@table @option @table @option
@item -f @var{fmt} (@emph{input/output}) @item -f @var{fmt} (@emph{input/output})
Force format. Force input or output file format. The format is normally autodetected for input
files and guessed from file extension for output files, so this option is not
needed in most cases.
@item -i @var{filename} (@emph{input}) @item -i @var{filename} (@emph{input})
input file name input file name
@item -y (@emph{global}) @item -y (@emph{global})
Overwrite output files. Overwrite output files without asking.
@item -c[:@var{stream_specifier}] @var{codec} (@emph{input/output,per-stream}) @item -c[:@var{stream_specifier}] @var{codec} (@emph{input/output,per-stream})
@itemx -codec[:@var{stream_specifier}] @var{codec} (@emph{input/output,per-stream}) @itemx -codec[:@var{stream_specifier}] @var{codec} (@emph{input/output,per-stream})
@ -111,9 +113,8 @@ will copy all the streams except the second video, which will be encoded with
libx264, and the 138th audio, which will be encoded with libvorbis. libx264, and the 138th audio, which will be encoded with libvorbis.
@item -t @var{duration} (@emph{output}) @item -t @var{duration} (@emph{output})
Restrict the transcoded/captured video sequence Stop writing the output after its duration reaches @var{duration}.
to the duration specified in seconds. @var{duration} may be a number in seconds, or in @code{hh:mm:ss[.xxx]} form.
@code{hh:mm:ss[.xxx]} syntax is also supported.
@item -fs @var{limit_size} (@emph{output}) @item -fs @var{limit_size} (@emph{output})
Set the file size limit. Set the file size limit.
@ -131,7 +132,7 @@ Set the input time offset in seconds.
@code{[-]hh:mm:ss[.xxx]} syntax is also supported. @code{[-]hh:mm:ss[.xxx]} syntax is also supported.
The offset is added to the timestamps of the input files. The offset is added to the timestamps of the input files.
Specifying a positive offset means that the corresponding Specifying a positive offset means that the corresponding
streams are delayed by 'offset' seconds. streams are delayed by @var{offset} seconds.
@item -metadata[:metadata_specifier] @var{key}=@var{value} (@emph{output,per-metadata}) @item -metadata[:metadata_specifier] @var{key}=@var{value} (@emph{output,per-metadata})
Set a metadata key/value pair. Set a metadata key/value pair.
@ -158,9 +159,10 @@ This option is deprecated and has no effect, use -loglevel
to set verbosity level. to set verbosity level.
@item -target @var{type} (@emph{output}) @item -target @var{type} (@emph{output})
Specify target file type ("vcd", "svcd", "dvd", "dv", "dv50", "pal-vcd", Specify target file type (@code{vcd}, @code{svcd}, @code{dvd}, @code{dv},
"ntsc-svcd", ... ). All the format options (bitrate, codecs, @code{dv50}). @var{type} may be prefixed with @code{pal-}, @code{ntsc-} or
buffer sizes) are then set automatically. You can just type: @code{film-} to use the corresponding standard. All the format options
(bitrate, codecs, buffer sizes) are then set automatically. You can just type:
@example @example
avconv -i myfile.avi -target vcd /tmp/vcd.mpg avconv -i myfile.avi -target vcd /tmp/vcd.mpg
@ -647,8 +649,10 @@ Show benchmarking information at the end of an encode.
Shows CPU time used and maximum memory consumption. Shows CPU time used and maximum memory consumption.
Maximum memory consumption is not supported on all systems, Maximum memory consumption is not supported on all systems,
it will usually display as 0 if not supported. it will usually display as 0 if not supported.
@item -timelimit @var{duration} (@emph{global})
Exit after avconv has been running for @var{duration} seconds.
@item -dump (@emph{global}) @item -dump (@emph{global})
Dump each input packet. Dump each input packet to stderr.
@item -hex (@emph{global}) @item -hex (@emph{global})
When dumping packets, also dump the payload. When dumping packets, also dump the payload.
@item -ps @var{size} @item -ps @var{size}

View File

@ -33,9 +33,10 @@ Possible forms of stream specifiers are:
Matches the stream with this index. E.g. @code{-threads:1 4} would set the Matches the stream with this index. E.g. @code{-threads:1 4} would set the
thread count for the second stream to 4. thread count for the second stream to 4.
@item @var{stream_type}[:@var{stream_index}] @item @var{stream_type}[:@var{stream_index}]
@var{stream_type} is one of: 'v' for video, 'a' for audio, 's' for subtitle and @var{stream_type} is one of: 'v' for video, 'a' for audio, 's' for subtitle,
'd' for data. If @var{stream_index} is given, then matches stream number 'd' for data and 't' for attachments. If @var{stream_index} is given, then
@var{stream_index} of this type. Otherwise matches all streams of this type. matches stream number @var{stream_index} of this type. Otherwise matches all
streams of this type.
@item @var{program_id}[:@var{stream_index}] @item @var{program_id}[:@var{stream_index}]
If @var{stream_index} is given, then matches stream number @var{stream_index} in If @var{stream_index} is given, then matches stream number @var{stream_index} in
program with id @var{program_id}. Otherwise matches all streams in this program. program with id @var{program_id}. Otherwise matches all streams in this program.

View File

@ -1598,7 +1598,6 @@ static int output_packet(InputStream *ist, int ist_index,
OutputStream *ost; OutputStream *ost;
int ret, i; int ret, i;
int got_output; int got_output;
AVFrame picture;
void *buffer_to_free = NULL; void *buffer_to_free = NULL;
static unsigned int samples_size= 0; static unsigned int samples_size= 0;
AVSubtitle subtitle, *subtitle_to_free; AVSubtitle subtitle, *subtitle_to_free;
@ -1633,6 +1632,7 @@ static int output_packet(InputStream *ist, int ist_index,
while (avpkt.size > 0 || (!pkt && got_output)) { while (avpkt.size > 0 || (!pkt && got_output)) {
uint8_t *data_buf, *decoded_data_buf; uint8_t *data_buf, *decoded_data_buf;
int data_size, decoded_data_size; int data_size, decoded_data_size;
AVFrame *decoded_frame, *filtered_frame;
handle_eof: handle_eof:
ist->pts= ist->next_pts; ist->pts= ist->next_pts;
@ -1642,6 +1642,7 @@ static int output_packet(InputStream *ist, int ist_index,
ist->showed_multi_packet_warning=1; ist->showed_multi_packet_warning=1;
/* decode the packet if needed */ /* decode the packet if needed */
decoded_frame = filtered_frame = NULL;
decoded_data_buf = NULL; /* fail safe */ decoded_data_buf = NULL; /* fail safe */
decoded_data_size= 0; decoded_data_size= 0;
data_buf = avpkt.data; data_buf = avpkt.data;
@ -1678,22 +1679,23 @@ static int output_packet(InputStream *ist, int ist_index,
break;} break;}
case AVMEDIA_TYPE_VIDEO: case AVMEDIA_TYPE_VIDEO:
decoded_data_size = (ist->st->codec->width * ist->st->codec->height * 3) / 2; decoded_data_size = (ist->st->codec->width * ist->st->codec->height * 3) / 2;
/* XXX: allocate picture correctly */ if (!(decoded_frame = avcodec_alloc_frame()))
avcodec_get_frame_defaults(&picture); return AVERROR(ENOMEM);
avpkt.pts = pkt_pts; avpkt.pts = pkt_pts;
avpkt.dts = ist->pts; avpkt.dts = ist->pts;
pkt_pts = AV_NOPTS_VALUE; pkt_pts = AV_NOPTS_VALUE;
ret = avcodec_decode_video2(ist->st->codec, ret = avcodec_decode_video2(ist->st->codec,
&picture, &got_output, &avpkt); decoded_frame, &got_output, &avpkt);
quality = same_quant ? picture.quality : 0; quality = same_quant ? decoded_frame->quality : 0;
if (ret < 0) if (ret < 0)
return ret; goto fail;
if (!got_output) { if (!got_output) {
/* no picture yet */ /* no picture yet */
av_freep(&decoded_frame);
goto discard_packet; goto discard_packet;
} }
ist->next_pts = ist->pts = picture.best_effort_timestamp; ist->next_pts = ist->pts = decoded_frame->best_effort_timestamp;
if (ist->st->codec->time_base.num != 0) { if (ist->st->codec->time_base.num != 0) {
int ticks= ist->st->parser ? ist->st->parser->repeat_pict+1 : ist->st->codec->ticks_per_frame; int ticks= ist->st->parser ? ist->st->parser->repeat_pict+1 : ist->st->codec->ticks_per_frame;
ist->next_pts += ((int64_t)AV_TIME_BASE * ist->next_pts += ((int64_t)AV_TIME_BASE *
@ -1702,7 +1704,7 @@ static int output_packet(InputStream *ist, int ist_index,
} }
avpkt.size = 0; avpkt.size = 0;
buffer_to_free = NULL; buffer_to_free = NULL;
pre_process_video_frame(ist, (AVPicture *)&picture, &buffer_to_free); pre_process_video_frame(ist, (AVPicture *)decoded_frame, &buffer_to_free);
break; break;
case AVMEDIA_TYPE_SUBTITLE: case AVMEDIA_TYPE_SUBTITLE:
ret = avcodec_decode_subtitle2(ist->st->codec, ret = avcodec_decode_subtitle2(ist->st->codec,
@ -1743,11 +1745,11 @@ static int output_packet(InputStream *ist, int ist_index,
if (of->start_time == 0 || ist->pts >= of->start_time) { if (of->start_time == 0 || ist->pts >= of->start_time) {
ost = &ost_table[i]; ost = &ost_table[i];
if (ost->input_video_filter && ost->source_index == ist_index) { if (ost->input_video_filter && ost->source_index == ist_index) {
if (!picture.sample_aspect_ratio.num) if (!decoded_frame->sample_aspect_ratio.num)
picture.sample_aspect_ratio = ist->st->sample_aspect_ratio; decoded_frame->sample_aspect_ratio = ist->st->sample_aspect_ratio;
picture.pts = ist->pts; decoded_frame->pts = ist->pts;
av_vsrc_buffer_add_frame(ost->input_video_filter, &picture, AV_VSRC_BUF_FLAG_OVERWRITE); av_vsrc_buffer_add_frame(ost->input_video_filter, decoded_frame, AV_VSRC_BUF_FLAG_OVERWRITE);
} }
} }
} }
@ -1800,11 +1802,18 @@ static int output_packet(InputStream *ist, int ist_index,
AVRational ist_pts_tb = ost->output_video_filter->inputs[0]->time_base; AVRational ist_pts_tb = ost->output_video_filter->inputs[0]->time_base;
if (av_buffersink_get_buffer_ref(ost->output_video_filter, &ost->picref, 0) < 0) if (av_buffersink_get_buffer_ref(ost->output_video_filter, &ost->picref, 0) < 0)
goto cont; goto cont;
if (!filtered_frame && !(filtered_frame = avcodec_alloc_frame())) {
ret = AVERROR(ENOMEM);
goto fail;
}
*filtered_frame= *decoded_frame; //for me_threshold
if (ost->picref) { if (ost->picref) {
avfilter_fill_frame_from_video_buffer_ref(&picture, ost->picref); avfilter_fill_frame_from_video_buffer_ref(filtered_frame, ost->picref);
ist->pts = av_rescale_q(ost->picref->pts, ist_pts_tb, AV_TIME_BASE_Q); ist->pts = av_rescale_q(ost->picref->pts, ist_pts_tb, AV_TIME_BASE_Q);
} }
} }
#else
filtered_frame = decoded_frame;
#endif #endif
os = output_files[ost->file_index].ctx; os = output_files[ost->file_index].ctx;
@ -1822,8 +1831,8 @@ static int output_packet(InputStream *ist, int ist_index,
if (ost->picref->video && !ost->frame_aspect_ratio) if (ost->picref->video && !ost->frame_aspect_ratio)
ost->st->codec->sample_aspect_ratio = ost->picref->video->sample_aspect_ratio; ost->st->codec->sample_aspect_ratio = ost->picref->video->sample_aspect_ratio;
#endif #endif
do_video_out(os, ost, ist, &picture, &frame_size, do_video_out(os, ost, ist, filtered_frame, &frame_size,
same_quant ? quality : ost->st->codec->global_quality); same_quant ? quality : ost->st->codec->global_quality);
if (vstats_filename && frame_size) if (vstats_filename && frame_size)
do_video_stats(os, ost, frame_size); do_video_stats(os, ost, frame_size);
break; break;
@ -1902,15 +1911,20 @@ static int output_packet(InputStream *ist, int ist_index,
ost->output_video_filter && avfilter_poll_frame(ost->output_video_filter->inputs[0]); ost->output_video_filter && avfilter_poll_frame(ost->output_video_filter->inputs[0]);
avfilter_unref_buffer(ost->picref); avfilter_unref_buffer(ost->picref);
} }
av_freep(&filtered_frame);
#endif #endif
} }
fail:
av_free(buffer_to_free); av_free(buffer_to_free);
/* XXX: allocate the subtitles in the codec ? */ /* XXX: allocate the subtitles in the codec ? */
if (subtitle_to_free) { if (subtitle_to_free) {
avsubtitle_free(subtitle_to_free); avsubtitle_free(subtitle_to_free);
subtitle_to_free = NULL; subtitle_to_free = NULL;
} }
av_freep(&decoded_frame);
if (ret < 0)
return ret;
} }
discard_packet: discard_packet:
@ -2082,6 +2096,7 @@ static int transcode_init(OutputFile *output_files, int nb_output_files,
codec->height = icodec->height; codec->height = icodec->height;
break; break;
case AVMEDIA_TYPE_DATA: case AVMEDIA_TYPE_DATA:
case AVMEDIA_TYPE_ATTACHMENT:
break; break;
default: default:
abort(); abort();
@ -3196,6 +3211,9 @@ static OutputStream *new_output_stream(OptionsContext *o, AVFormatContext *oc, e
st->codec->global_quality = FF_QP2LAMBDA * qscale; st->codec->global_quality = FF_QP2LAMBDA * qscale;
} }
if (oc->oformat->flags & AVFMT_GLOBALHEADER)
st->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;
ost->sws_flags = av_get_int(sws_opts, "sws_flags", NULL); ost->sws_flags = av_get_int(sws_opts, "sws_flags", NULL);
return ost; return ost;
} }
@ -3227,10 +3245,6 @@ static OutputStream *new_video_stream(OptionsContext *o, AVFormatContext *oc)
st = ost->st; st = ost->st;
video_enc = st->codec; video_enc = st->codec;
if(oc->oformat->flags & AVFMT_GLOBALHEADER) {
video_enc->flags |= CODEC_FLAG_GLOBAL_HEADER;
}
if (!st->stream_copy) { if (!st->stream_copy) {
const char *p = NULL; const char *p = NULL;
char *forced_key_frames = NULL, *frame_rate = NULL, *frame_size = NULL; char *forced_key_frames = NULL, *frame_rate = NULL, *frame_size = NULL;
@ -3351,9 +3365,6 @@ static OutputStream *new_audio_stream(OptionsContext *o, AVFormatContext *oc)
audio_enc = st->codec; audio_enc = st->codec;
audio_enc->codec_type = AVMEDIA_TYPE_AUDIO; audio_enc->codec_type = AVMEDIA_TYPE_AUDIO;
if (oc->oformat->flags & AVFMT_GLOBALHEADER) {
audio_enc->flags |= CODEC_FLAG_GLOBAL_HEADER;
}
if (!st->stream_copy) { if (!st->stream_copy) {
char *sample_fmt = NULL; char *sample_fmt = NULL;
@ -3376,20 +3387,21 @@ static OutputStream *new_data_stream(OptionsContext *o, AVFormatContext *oc)
{ {
AVStream *st; AVStream *st;
OutputStream *ost; OutputStream *ost;
AVCodecContext *data_enc;
ost = new_output_stream(o, oc, AVMEDIA_TYPE_DATA); ost = new_output_stream(o, oc, AVMEDIA_TYPE_DATA);
st = ost->st; st = ost->st;
data_enc = st->codec;
if (!st->stream_copy) { if (!st->stream_copy) {
av_log(NULL, AV_LOG_FATAL, "Data stream encoding not supported yet (only streamcopy)\n"); av_log(NULL, AV_LOG_FATAL, "Data stream encoding not supported yet (only streamcopy)\n");
exit_program(1); exit_program(1);
} }
if (oc->oformat->flags & AVFMT_GLOBALHEADER) { return ost;
data_enc->flags |= CODEC_FLAG_GLOBAL_HEADER; }
}
static OutputStream *new_attachment_stream(OptionsContext *o, AVFormatContext *oc)
{
OutputStream *ost = new_output_stream(o, oc, AVMEDIA_TYPE_ATTACHMENT);
ost->st->stream_copy = 1;
return ost; return ost;
} }
@ -3405,10 +3417,6 @@ static OutputStream *new_subtitle_stream(OptionsContext *o, AVFormatContext *oc)
subtitle_enc->codec_type = AVMEDIA_TYPE_SUBTITLE; subtitle_enc->codec_type = AVMEDIA_TYPE_SUBTITLE;
if (oc->oformat->flags & AVFMT_GLOBALHEADER) {
subtitle_enc->flags |= CODEC_FLAG_GLOBAL_HEADER;
}
return ost; return ost;
} }
@ -3596,6 +3604,7 @@ static void opt_output_file(void *optctx, const char *filename)
case AVMEDIA_TYPE_AUDIO: ost = new_audio_stream(o, oc); break; case AVMEDIA_TYPE_AUDIO: ost = new_audio_stream(o, oc); break;
case AVMEDIA_TYPE_SUBTITLE: ost = new_subtitle_stream(o, oc); break; case AVMEDIA_TYPE_SUBTITLE: ost = new_subtitle_stream(o, oc); break;
case AVMEDIA_TYPE_DATA: ost = new_data_stream(o, oc); break; case AVMEDIA_TYPE_DATA: ost = new_data_stream(o, oc); break;
case AVMEDIA_TYPE_ATTACHMENT: ost = new_attachment_stream(o, oc); break;
default: default:
av_log(NULL, AV_LOG_FATAL, "Cannot map stream #%d.%d - unsupported type.\n", av_log(NULL, AV_LOG_FATAL, "Cannot map stream #%d.%d - unsupported type.\n",
map->file_index, map->stream_index); map->file_index, map->stream_index);

View File

@ -1632,6 +1632,7 @@ static int matroska_read_header(AVFormatContext *s, AVFormatParameters *ap)
if (st == NULL) if (st == NULL)
break; break;
av_dict_set(&st->metadata, "filename",attachements[j].filename, 0); av_dict_set(&st->metadata, "filename",attachements[j].filename, 0);
av_dict_set(&st->metadata, "mimetype", attachements[j].mime, 0);
st->codec->codec_id = CODEC_ID_NONE; st->codec->codec_id = CODEC_ID_NONE;
st->codec->codec_type = AVMEDIA_TYPE_ATTACHMENT; st->codec->codec_type = AVMEDIA_TYPE_ATTACHMENT;
st->codec->extradata = av_malloc(attachements[j].bin.size); st->codec->extradata = av_malloc(attachements[j].bin.size);

View File

@ -91,6 +91,8 @@ typedef struct MatroskaMuxContext {
unsigned int audio_buffer_size; unsigned int audio_buffer_size;
AVPacket cur_audio_pkt; AVPacket cur_audio_pkt;
int have_attachments;
} MatroskaMuxContext; } MatroskaMuxContext;
@ -528,6 +530,11 @@ static int mkv_write_tracks(AVFormatContext *s)
int output_sample_rate = 0; int output_sample_rate = 0;
AVDictionaryEntry *tag; AVDictionaryEntry *tag;
if (codec->codec_type == AVMEDIA_TYPE_ATTACHMENT) {
mkv->have_attachments = 1;
continue;
}
if (!bit_depth) if (!bit_depth)
bit_depth = av_get_bytes_per_sample(codec->sample_fmt) << 3; bit_depth = av_get_bytes_per_sample(codec->sample_fmt) << 3;
@ -804,6 +811,68 @@ static int mkv_write_tags(AVFormatContext *s)
return 0; return 0;
} }
static int mkv_write_attachments(AVFormatContext *s)
{
MatroskaMuxContext *mkv = s->priv_data;
AVIOContext *pb = s->pb;
ebml_master attachments;
AVLFG c;
int i, ret;
if (!mkv->have_attachments)
return 0;
av_lfg_init(&c, av_get_random_seed());
ret = mkv_add_seekhead_entry(mkv->main_seekhead, MATROSKA_ID_ATTACHMENTS, avio_tell(pb));
if (ret < 0) return ret;
attachments = start_ebml_master(pb, MATROSKA_ID_ATTACHMENTS, 0);
for (i = 0; i < s->nb_streams; i++) {
AVStream *st = s->streams[i];
ebml_master attached_file;
AVDictionaryEntry *t;
const char *mimetype = NULL;
if (st->codec->codec_type != AVMEDIA_TYPE_ATTACHMENT)
continue;
attached_file = start_ebml_master(pb, MATROSKA_ID_ATTACHEDFILE, 0);
if (t = av_dict_get(st->metadata, "title", NULL, 0))
put_ebml_string(pb, MATROSKA_ID_FILEDESC, t->value);
if (!(t = av_dict_get(st->metadata, "filename", NULL, 0))) {
av_log(s, AV_LOG_ERROR, "Attachment stream %d has no filename tag.\n", i);
return AVERROR(EINVAL);
}
put_ebml_string(pb, MATROSKA_ID_FILENAME, t->value);
if (t = av_dict_get(st->metadata, "mimetype", NULL, 0))
mimetype = t->value;
else if (st->codec->codec_id != CODEC_ID_NONE ) {
int i;
for (i = 0; ff_mkv_mime_tags[i].id != CODEC_ID_NONE; i++)
if (ff_mkv_mime_tags[i].id == st->codec->codec_id) {
mimetype = ff_mkv_mime_tags[i].str;
break;
}
}
if (!mimetype) {
av_log(s, AV_LOG_ERROR, "Attachment stream %d has no mimetype tag and "
"it cannot be deduced from the codec id.\n", i);
return AVERROR(EINVAL);
}
put_ebml_string(pb, MATROSKA_ID_FILEMIMETYPE, mimetype);
put_ebml_binary(pb, MATROSKA_ID_FILEDATA, st->codec->extradata, st->codec->extradata_size);
put_ebml_uint(pb, MATROSKA_ID_FILEUID, av_lfg_get(&c));
end_ebml_master(pb, attached_file);
}
end_ebml_master(pb, attachments);
return 0;
}
static int mkv_write_header(AVFormatContext *s) static int mkv_write_header(AVFormatContext *s)
{ {
MatroskaMuxContext *mkv = s->priv_data; MatroskaMuxContext *mkv = s->priv_data;
@ -877,6 +946,9 @@ static int mkv_write_header(AVFormatContext *s)
ret = mkv_write_tags(s); ret = mkv_write_tags(s);
if (ret < 0) return ret; if (ret < 0) return ret;
ret = mkv_write_attachments(s);
if (ret < 0) return ret;
} }
if (!s->pb->seekable) if (!s->pb->seekable)