| ... | ... |
@@ -275,6 +275,8 @@ typedef struct OptionsContext {
|
| 275 | 275 |
|
| 276 | 276 |
SpecifierOpt *ts_scale; |
| 277 | 277 |
int nb_ts_scale; |
| 278 |
+ SpecifierOpt *dump_attachment; |
|
| 279 |
+ int nb_dump_attachment; |
|
| 278 | 280 |
|
| 279 | 281 |
/* output options */ |
| 280 | 282 |
StreamMap *stream_maps; |
| ... | ... |
@@ -2843,6 +2845,60 @@ static void add_input_streams(OptionsContext *o, AVFormatContext *ic) |
| 2843 | 2843 |
} |
| 2844 | 2844 |
} |
| 2845 | 2845 |
|
| 2846 |
+static void assert_file_overwrite(const char *filename) |
|
| 2847 |
+{
|
|
| 2848 |
+ if (!file_overwrite && |
|
| 2849 |
+ (strchr(filename, ':') == NULL || filename[1] == ':' || |
|
| 2850 |
+ av_strstart(filename, "file:", NULL))) {
|
|
| 2851 |
+ if (avio_check(filename, 0) == 0) {
|
|
| 2852 |
+ if (!using_stdin) {
|
|
| 2853 |
+ fprintf(stderr,"File '%s' already exists. Overwrite ? [y/N] ", filename); |
|
| 2854 |
+ fflush(stderr); |
|
| 2855 |
+ if (!read_yesno()) {
|
|
| 2856 |
+ fprintf(stderr, "Not overwriting - exiting\n"); |
|
| 2857 |
+ exit_program(1); |
|
| 2858 |
+ } |
|
| 2859 |
+ } |
|
| 2860 |
+ else {
|
|
| 2861 |
+ fprintf(stderr,"File '%s' already exists. Exiting.\n", filename); |
|
| 2862 |
+ exit_program(1); |
|
| 2863 |
+ } |
|
| 2864 |
+ } |
|
| 2865 |
+ } |
|
| 2866 |
+} |
|
| 2867 |
+ |
|
| 2868 |
+static void dump_attachment(AVStream *st, const char *filename) |
|
| 2869 |
+{
|
|
| 2870 |
+ int ret; |
|
| 2871 |
+ AVIOContext *out = NULL; |
|
| 2872 |
+ AVDictionaryEntry *e; |
|
| 2873 |
+ |
|
| 2874 |
+ if (!st->codec->extradata_size) {
|
|
| 2875 |
+ av_log(NULL, AV_LOG_WARNING, "No extradata to dump in stream #%d:%d.\n", |
|
| 2876 |
+ nb_input_files - 1, st->index); |
|
| 2877 |
+ return; |
|
| 2878 |
+ } |
|
| 2879 |
+ if (!*filename && (e = av_dict_get(st->metadata, "filename", NULL, 0))) |
|
| 2880 |
+ filename = e->value; |
|
| 2881 |
+ if (!*filename) {
|
|
| 2882 |
+ av_log(NULL, AV_LOG_FATAL, "No filename specified and no 'filename' tag" |
|
| 2883 |
+ "in stream #%d:%d.\n", nb_input_files - 1, st->index); |
|
| 2884 |
+ exit_program(1); |
|
| 2885 |
+ } |
|
| 2886 |
+ |
|
| 2887 |
+ assert_file_overwrite(filename); |
|
| 2888 |
+ |
|
| 2889 |
+ if ((ret = avio_open (&out, filename, AVIO_FLAG_WRITE)) < 0) {
|
|
| 2890 |
+ av_log(NULL, AV_LOG_FATAL, "Could not open file %s for writing.\n", |
|
| 2891 |
+ filename); |
|
| 2892 |
+ exit_program(1); |
|
| 2893 |
+ } |
|
| 2894 |
+ |
|
| 2895 |
+ avio_write(out, st->codec->extradata, st->codec->extradata_size); |
|
| 2896 |
+ avio_flush(out); |
|
| 2897 |
+ avio_close(out); |
|
| 2898 |
+} |
|
| 2899 |
+ |
|
| 2846 | 2900 |
static int opt_input_file(OptionsContext *o, const char *opt, const char *filename) |
| 2847 | 2901 |
{
|
| 2848 | 2902 |
AVFormatContext *ic; |
| ... | ... |
@@ -2943,6 +2999,17 @@ static int opt_input_file(OptionsContext *o, const char *opt, const char *filena |
| 2943 | 2943 |
input_files[nb_input_files - 1].nb_streams = ic->nb_streams; |
| 2944 | 2944 |
input_files[nb_input_files - 1].rate_emu = o->rate_emu; |
| 2945 | 2945 |
|
| 2946 |
+ for (i = 0; i < o->nb_dump_attachment; i++) {
|
|
| 2947 |
+ int j; |
|
| 2948 |
+ |
|
| 2949 |
+ for (j = 0; j < ic->nb_streams; j++) {
|
|
| 2950 |
+ AVStream *st = ic->streams[j]; |
|
| 2951 |
+ |
|
| 2952 |
+ if (check_stream_specifier(ic, st, o->dump_attachment[i].specifier) == 1) |
|
| 2953 |
+ dump_attachment(st, o->dump_attachment[i].u.str); |
|
| 2954 |
+ } |
|
| 2955 |
+ } |
|
| 2956 |
+ |
|
| 2946 | 2957 |
for (i = 0; i < orig_nb_streams; i++) |
| 2947 | 2958 |
av_dict_free(&opts[i]); |
| 2948 | 2959 |
av_freep(&opts); |
| ... | ... |
@@ -3602,25 +3669,7 @@ static void opt_output_file(void *optctx, const char *filename) |
| 3602 | 3602 |
|
| 3603 | 3603 |
if (!(oc->oformat->flags & AVFMT_NOFILE)) {
|
| 3604 | 3604 |
/* test if it already exists to avoid loosing precious files */ |
| 3605 |
- if (!file_overwrite && |
|
| 3606 |
- (strchr(filename, ':') == NULL || |
|
| 3607 |
- filename[1] == ':' || |
|
| 3608 |
- av_strstart(filename, "file:", NULL))) {
|
|
| 3609 |
- if (avio_check(filename, 0) == 0) {
|
|
| 3610 |
- if (!using_stdin) {
|
|
| 3611 |
- fprintf(stderr,"File '%s' already exists. Overwrite ? [y/N] ", filename); |
|
| 3612 |
- fflush(stderr); |
|
| 3613 |
- if (!read_yesno()) {
|
|
| 3614 |
- fprintf(stderr, "Not overwriting - exiting\n"); |
|
| 3615 |
- exit_program(1); |
|
| 3616 |
- } |
|
| 3617 |
- } |
|
| 3618 |
- else {
|
|
| 3619 |
- fprintf(stderr,"File '%s' already exists. Exiting.\n", filename); |
|
| 3620 |
- exit_program(1); |
|
| 3621 |
- } |
|
| 3622 |
- } |
|
| 3623 |
- } |
|
| 3605 |
+ assert_file_overwrite(filename); |
|
| 3624 | 3606 |
|
| 3625 | 3607 |
/* open the file */ |
| 3626 | 3608 |
if ((err = avio_open(&oc->pb, filename, AVIO_FLAG_WRITE)) < 0) {
|
| ... | ... |
@@ -4086,6 +4135,7 @@ static const OptionDef options[] = {
|
| 4086 | 4086 |
#endif |
| 4087 | 4087 |
{ "stats", OPT_BOOL, {&print_stats}, "print progress report during encoding", },
|
| 4088 | 4088 |
{ "attach", HAS_ARG | OPT_FUNC2, {(void*)opt_attach}, "add an attachment to the output file", "filename" },
|
| 4089 |
+ { "dump_attachment", HAS_ARG | OPT_STRING | OPT_SPEC, {.off = OFFSET(dump_attachment)}, "extract an attachment into a file", "filename" },
|
|
| 4089 | 4090 |
|
| 4090 | 4091 |
/* video options */ |
| 4091 | 4092 |
{ "vframes", HAS_ARG | OPT_VIDEO | OPT_FUNC2, {(void*)opt_video_frames}, "set the number of video frames to record", "number" },
|
| ... | ... |
@@ -207,6 +207,24 @@ avconv -i INPUT -attach DejaVuSans.ttf -metadata:s:2 mimetype=application/x-true |
| 207 | 207 |
@end example |
| 208 | 208 |
(assuming that the attachment stream will be third in the output file). |
| 209 | 209 |
|
| 210 |
+@item -dump_attachment[:@var{stream_specifier}] @var{filename} (@emph{input,per-stream})
|
|
| 211 |
+Extract the matching attachment stream into a file named @var{filename}. If
|
|
| 212 |
+@var{filename} is empty, then the value of the @code{filename} metadata tag
|
|
| 213 |
+will be used. |
|
| 214 |
+ |
|
| 215 |
+E.g. to extract the first attachment to a file named 'out.ttf': |
|
| 216 |
+@example |
|
| 217 |
+avconv -dump_attachment:t:0 out.ttf INPUT |
|
| 218 |
+@end example |
|
| 219 |
+To extract all attachments to files determined by the @code{filename} tag:
|
|
| 220 |
+@example |
|
| 221 |
+avconv -dump_attachment:t "" INPUT |
|
| 222 |
+@end example |
|
| 223 |
+ |
|
| 224 |
+Technical note -- attachments are implemented as codec extradata, so this |
|
| 225 |
+option can actually be used to extract extradata from any stream, not just |
|
| 226 |
+attachments. |
|
| 227 |
+ |
|
| 210 | 228 |
@end table |
| 211 | 229 |
|
| 212 | 230 |
@section Video Options |