X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=ffmpeg.c;h=8a5e0e4ed1b94837563574926bafb18a9d81d6a4;hb=46a7e3ec14941fb363a95c37ec10083a2730e9e8;hp=b196f58462f1a6bfde117eafaf7f1aa7846331aa;hpb=22730e8790a42c2873fd424d7ba66af95e0ab573;p=ffmpeg diff --git a/ffmpeg.c b/ffmpeg.c index b196f58462f..8a5e0e4ed1b 100644 --- a/ffmpeg.c +++ b/ffmpeg.c @@ -34,30 +34,29 @@ #include "libavformat/avformat.h" #include "libavdevice/avdevice.h" #include "libswscale/swscale.h" -#include "libavformat/framehook.h" #include "libavcodec/opt.h" #include "libavcodec/audioconvert.h" #include "libavutil/fifo.h" #include "libavutil/avstring.h" #include "libavformat/os_support.h" -#ifdef HAVE_SYS_RESOURCE_H +#if HAVE_SYS_RESOURCE_H #include #include -#elif defined(HAVE_GETPROCESSTIMES) +#elif HAVE_GETPROCESSTIMES #include #endif -#ifdef HAVE_SYS_SELECT_H +#if HAVE_SYS_SELECT_H #include #endif -#ifdef HAVE_TERMIOS_H +#if HAVE_TERMIOS_H #include #include #include #include -#elif defined(HAVE_CONIO_H) +#elif HAVE_CONIO_H #include #endif #undef time //needed because HAVE_AV_CONFIG_H is defined on top @@ -172,12 +171,8 @@ static int64_t start_time = 0; static int64_t rec_timestamp = 0; static int64_t input_ts_offset = 0; static int file_overwrite = 0; -static char *str_title = NULL; -static char *str_author = NULL; -static char *str_copyright = NULL; -static char *str_comment = NULL; -static char *str_genre = NULL; -static char *str_album = NULL; +static int metadata_count; +static AVMetadataTag *metadata; static int do_benchmark = 0; static int do_hex_dump = 0; static int do_pkt_dump = 0; @@ -207,7 +202,6 @@ static int audio_volume = 256; static int exit_on_error = 0; static int using_stdin = 0; -static int using_vhook = 0; static int verbose = 1; static int thread_count= 1; static int q_pressed = 0; @@ -269,7 +263,7 @@ typedef struct AVOutputStream { ReSampleContext *resample; /* for audio resampling */ int reformat_pair; AVAudioConvert *reformat_ctx; - AVFifoBuffer fifo; /* for compression: one audio fifo per codec */ + AVFifoBuffer *fifo; /* for compression: one audio fifo per codec */ FILE *logfile; } AVOutputStream; @@ -295,7 +289,7 @@ typedef struct AVInputFile { int nb_streams; /* nb streams we are aware of */ } AVInputFile; -#ifdef HAVE_TERMIOS_H +#if HAVE_TERMIOS_H /* init terminal so that we can grab keys */ static struct termios oldtty; @@ -303,7 +297,7 @@ static struct termios oldtty; static void term_exit(void) { -#ifdef HAVE_TERMIOS_H +#if HAVE_TERMIOS_H tcsetattr (0, TCSANOW, &oldtty); #endif } @@ -319,7 +313,7 @@ sigterm_handler(int sig) static void term_init(void) { -#ifdef HAVE_TERMIOS_H +#if HAVE_TERMIOS_H struct termios tty; tcgetattr (0, &tty); @@ -344,7 +338,7 @@ static void term_init(void) register a function to be called at normal program termination */ atexit(term_exit); -#ifdef CONFIG_BEOS_NETSERVER +#if CONFIG_BEOS_NETSERVER fcntl(0, F_SETFL, fcntl(0, F_GETFL) | O_NONBLOCK); #endif } @@ -352,10 +346,10 @@ static void term_init(void) /* read a key without blocking */ static int read_key(void) { -#if defined(HAVE_TERMIOS_H) +#if HAVE_TERMIOS_H int n = 1; unsigned char ch; -#ifndef CONFIG_BEOS_NETSERVER +#if !CONFIG_BEOS_NETSERVER struct timeval tv; fd_set rfds; @@ -372,7 +366,7 @@ static int read_key(void) return n; } -#elif defined(HAVE_CONIO_H) +#elif HAVE_CONIO_H if(kbhit()) return(getch()); #endif @@ -396,9 +390,17 @@ static int av_exit(int ret) if (!(s->oformat->flags & AVFMT_NOFILE) && s->pb) url_fclose(s->pb); for(j=0;jnb_streams;j++) { + av_metadata_free(&s->streams[j]->metadata); av_free(s->streams[j]->codec); av_free(s->streams[j]); } + for(j=0;jnb_programs;j++) { + av_metadata_free(&s->programs[j]->metadata); + } + for(j=0;jnb_chapters;j++) { + av_metadata_free(&s->chapters[j]->metadata); + } + av_metadata_free(&s->metadata); av_free(s); } for(i=0;iaudio_resample = 1; if (ost->audio_resample && !ost->resample) { - if (dec->sample_fmt != SAMPLE_FMT_S16) { - fprintf(stderr, "Audio resampler only works with 16 bits per sample, patch welcome.\n"); - av_exit(1); - } - ost->resample = audio_resample_init(enc->channels, dec->channels, - enc->sample_rate, dec->sample_rate); + if (dec->sample_fmt != SAMPLE_FMT_S16) + fprintf(stderr, "Warning, using s16 intermediate sample format for resampling\n"); + ost->resample = av_audio_resample_init(enc->channels, dec->channels, + enc->sample_rate, dec->sample_rate, + enc->sample_fmt, dec->sample_fmt, + 16, 10, 0, 0.8); if (!ost->resample) { fprintf(stderr, "Can not resample %d channels @ %d Hz to %d channels @ %d Hz\n", dec->channels, dec->sample_rate, @@ -562,7 +564,7 @@ static void do_audio_out(AVFormatContext *s, } #define MAKE_SFMT_PAIR(a,b) ((a)+SAMPLE_FMT_NB*(b)) - if (dec->sample_fmt!=enc->sample_fmt && + if (!ost->audio_resample && dec->sample_fmt!=enc->sample_fmt && MAKE_SFMT_PAIR(enc->sample_fmt,dec->sample_fmt)!=ost->reformat_pair) { if (!audio_out2) audio_out2 = av_malloc(audio_out_size); @@ -583,7 +585,7 @@ static void do_audio_out(AVFormatContext *s, if(audio_sync_method){ double delta = get_sync_ipts(ost) * enc->sample_rate - ost->sync_opts - - av_fifo_size(&ost->fifo)/(ost->st->codec->channels * 2); + - av_fifo_size(ost->fifo)/(ost->st->codec->channels * 2); double idelta= delta*ist->st->codec->sample_rate / enc->sample_rate; int byte_delta= ((int)idelta)*2*ist->st->codec->channels; @@ -620,13 +622,13 @@ static void do_audio_out(AVFormatContext *s, assert(ost->audio_resample); if(verbose > 2) fprintf(stderr, "compensating audio timestamp drift:%f compensation:%d in:%d\n", delta, comp, enc->sample_rate); -// fprintf(stderr, "drift:%f len:%d opts:%"PRId64" ipts:%"PRId64" fifo:%d\n", delta, -1, ost->sync_opts, (int64_t)(get_sync_ipts(ost) * enc->sample_rate), av_fifo_size(&ost->fifo)/(ost->st->codec->channels * 2)); +// fprintf(stderr, "drift:%f len:%d opts:%"PRId64" ipts:%"PRId64" fifo:%d\n", delta, -1, ost->sync_opts, (int64_t)(get_sync_ipts(ost) * enc->sample_rate), av_fifo_size(ost->fifo)/(ost->st->codec->channels * 2)); av_resample_compensate(*(struct AVResampleContext**)ost->resample, comp, enc->sample_rate); } } }else ost->sync_opts= lrintf(get_sync_ipts(ost) * enc->sample_rate) - - av_fifo_size(&ost->fifo)/(ost->st->codec->channels * 2); //FIXME wrong + - av_fifo_size(ost->fifo)/(ost->st->codec->channels * 2); //FIXME wrong if (ost->audio_resample) { buftmp = audio_buf; @@ -639,7 +641,7 @@ static void do_audio_out(AVFormatContext *s, size_out = size; } - if (dec->sample_fmt!=enc->sample_fmt) { + if (!ost->audio_resample && dec->sample_fmt!=enc->sample_fmt) { const void *ibuf[6]= {buftmp}; void *obuf[6]= {audio_out2}; int istride[6]= {isize}; @@ -658,24 +660,28 @@ static void do_audio_out(AVFormatContext *s, /* now encode as many frames as possible */ if (enc->frame_size > 1) { /* output resampled raw samples */ - if (av_fifo_realloc2(&ost->fifo, av_fifo_size(&ost->fifo) + size_out) < 0) { + if (av_fifo_realloc2(ost->fifo, av_fifo_size(ost->fifo) + size_out) < 0) { fprintf(stderr, "av_fifo_realloc2() failed\n"); av_exit(1); } - av_fifo_generic_write(&ost->fifo, buftmp, size_out, NULL); + av_fifo_generic_write(ost->fifo, buftmp, size_out, NULL); frame_bytes = enc->frame_size * osize * enc->channels; - while (av_fifo_size(&ost->fifo) >= frame_bytes) { + while (av_fifo_size(ost->fifo) >= frame_bytes) { AVPacket pkt; av_init_packet(&pkt); - av_fifo_read(&ost->fifo, audio_buf, frame_bytes); + av_fifo_generic_read(ost->fifo, frame_bytes, NULL, audio_buf); //FIXME pass ost->sync_opts as AVFrame.pts in avcodec_encode_audio() ret = avcodec_encode_audio(enc, audio_out, audio_out_size, (short *)audio_buf); + if (ret < 0) { + fprintf(stderr, "Audio encoding failed\n"); + av_exit(1); + } audio_size += ret; pkt.stream_index= ost->index; pkt.data= audio_out; @@ -703,6 +709,10 @@ static void do_audio_out(AVFormatContext *s, //FIXME pass ost->sync_opts as AVFrame.pts in avcodec_encode_audio() ret = avcodec_encode_audio(enc, audio_out, size_out, (short *)buftmp); + if (ret < 0) { + fprintf(stderr, "Audio encoding failed\n"); + av_exit(1); + } audio_size += ret; pkt.stream_index= ost->index; pkt.data= audio_out; @@ -724,7 +734,7 @@ static void pre_process_video_frame(AVInputStream *ist, AVPicture *picture, void dec = ist->st->codec; /* deinterlace : must be done before any resize */ - if (do_deinterlace || using_vhook) { + if (do_deinterlace) { int size; /* create temporary picture */ @@ -752,10 +762,6 @@ static void pre_process_video_frame(AVInputStream *ist, AVPicture *picture, void picture2 = picture; } - if (ENABLE_VHOOK) - frame_hook_process(picture2, dec->pix_fmt, dec->width, dec->height, - 1000000 * ist->pts / AV_TIME_BASE); - if (picture != picture2) *picture = *picture2; *bufp = buf; @@ -849,11 +855,14 @@ static void do_video_out(AVFormatContext *s, //FIXME set to 0.5 after we fix some dts/pts bugs like in avidec.c if (vdelta < -1.1) nb_frames = 0; - else if (video_sync_method == 2) + else if (video_sync_method == 2 || (video_sync_method<0 && (s->oformat->flags & AVFMT_VARIABLE_FPS))){ + if(vdelta<=-0.6){ + nb_frames=0; + }else if(vdelta>0.6) ost->sync_opts= lrintf(get_sync_ipts(ost) / av_q2d(enc->time_base)); - else if (vdelta > 1.1) + }else if (vdelta > 1.1) nb_frames = lrintf(vdelta); -//fprintf(stderr, "vdelta:%f, ost->sync_opts:%"PRId64", ost->sync_ipts:%f nb_frames:%d\n", vdelta, ost->sync_opts, ost->sync_ipts, nb_frames); +//fprintf(stderr, "vdelta:%f, ost->sync_opts:%"PRId64", ost->sync_ipts:%f nb_frames:%d\n", vdelta, ost->sync_opts, get_sync_ipts(ost), nb_frames); if (nb_frames == 0){ ++nb_frames_drop; if (verbose>2) @@ -872,7 +881,7 @@ static void do_video_out(AVFormatContext *s, if (ost->video_crop) { if (av_picture_crop((AVPicture *)&picture_crop_temp, (AVPicture *)in_picture, dec->pix_fmt, ost->topBand, ost->leftBand) < 0) { - av_log(NULL, AV_LOG_ERROR, "error cropping picture\n"); + fprintf(stderr, "error cropping picture\n"); if (exit_on_error) av_exit(1); return; @@ -889,7 +898,7 @@ static void do_video_out(AVFormatContext *s, final_picture = &ost->pict_tmp; if (ost->video_resample) { if (av_picture_crop((AVPicture *)&picture_pad_temp, (AVPicture *)final_picture, enc->pix_fmt, ost->padtop, ost->padleft) < 0) { - av_log(NULL, AV_LOG_ERROR, "error padding picture\n"); + fprintf(stderr, "error padding picture\n"); if (exit_on_error) av_exit(1); return; @@ -937,7 +946,7 @@ static void do_video_out(AVFormatContext *s, /* better than nothing: use input picture interlaced settings */ big_picture.interlaced_frame = in_picture->interlaced_frame; - if(avctx_opts[CODEC_TYPE_VIDEO]->flags & (CODEC_FLAG_INTERLACED_DCT|CODEC_FLAG_INTERLACED_ME)){ + if(avcodec_opts[CODEC_TYPE_VIDEO]->flags & (CODEC_FLAG_INTERLACED_DCT|CODEC_FLAG_INTERLACED_ME)){ if(top_field_first == -1) big_picture.top_field_first = in_picture->top_field_first; else @@ -959,7 +968,7 @@ static void do_video_out(AVFormatContext *s, ret = avcodec_encode_video(enc, bit_buffer, bit_buffer_size, &big_picture); - if (ret == -1) { + if (ret < 0) { fprintf(stderr, "Video encoding failed\n"); av_exit(1); } @@ -1245,8 +1254,9 @@ static int output_packet(AVInputStream *ist, int ist_index, goto discard_packet; } 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; ist->next_pts += ((int64_t)AV_TIME_BASE * - ist->st->codec->time_base.num) / + ist->st->codec->time_base.num * ticks) / ist->st->codec->time_base.den; } len = 0; @@ -1273,8 +1283,9 @@ static int output_packet(AVInputStream *ist, int ist_index, break; case CODEC_TYPE_VIDEO: 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; ist->next_pts += ((int64_t)AV_TIME_BASE * - ist->st->codec->time_base.num) / + ist->st->codec->time_base.num * ticks) / ist->st->codec->time_base.den; } break; @@ -1401,8 +1412,9 @@ static int output_packet(AVInputStream *ist, int ist_index, if (subtitle_to_free) { if (subtitle_to_free->rects != NULL) { for (i = 0; i < subtitle_to_free->num_rects; i++) { - av_free(subtitle_to_free->rects[i].bitmap); - av_free(subtitle_to_free->rects[i].rgba_palette); + av_freep(&subtitle_to_free->rects[i]->pict.data[0]); + av_freep(&subtitle_to_free->rects[i]->pict.data[1]); + av_freep(&subtitle_to_free->rects[i]); } av_freep(&subtitle_to_free->rects); } @@ -1434,24 +1446,32 @@ static int output_packet(AVInputStream *ist, int ist_index, switch(ost->st->codec->codec_type) { case CODEC_TYPE_AUDIO: - fifo_bytes = av_fifo_size(&ost->fifo); + fifo_bytes = av_fifo_size(ost->fifo); ret = 0; /* encode any samples remaining in fifo */ if(fifo_bytes > 0 && enc->codec->capabilities & CODEC_CAP_SMALL_LAST_FRAME) { int fs_tmp = enc->frame_size; enc->frame_size = fifo_bytes / (2 * enc->channels); - av_fifo_read(&ost->fifo, (uint8_t *)samples, fifo_bytes); + av_fifo_generic_read(ost->fifo, fifo_bytes, NULL, samples); ret = avcodec_encode_audio(enc, bit_buffer, bit_buffer_size, samples); enc->frame_size = fs_tmp; } if(ret <= 0) { ret = avcodec_encode_audio(enc, bit_buffer, bit_buffer_size, NULL); } + if (ret < 0) { + fprintf(stderr, "Audio encoding failed\n"); + av_exit(1); + } audio_size += ret; pkt.flags |= PKT_FLAG_KEY; break; case CODEC_TYPE_VIDEO: ret = avcodec_encode_video(enc, bit_buffer, bit_buffer_size, NULL); + if (ret < 0) { + fprintf(stderr, "Video encoding failed\n"); + av_exit(1); + } video_size += ret; if(enc->coded_frame && enc->coded_frame->key_frame) pkt.flags |= PKT_FLAG_KEY; @@ -1533,6 +1553,8 @@ static int av_encode(AVFormatContext **output_files, AVInputFile *file_table; int key; int want_sdp = 1; + uint8_t no_packet[MAX_FILES]={0}; + int no_packet_count=0; file_table= av_mallocz(nb_input_files * sizeof(AVInputFile)); if (!file_table) @@ -1695,6 +1717,7 @@ static int av_encode(AVFormatContext **output_files, /* for each output stream, we compute the right encoding parameters */ for(i=0;ifile_index]; ist = ist_table[ost->source_index]; @@ -1702,9 +1725,9 @@ static int av_encode(AVFormatContext **output_files, codec = ost->st->codec; icodec = ist->st->codec; - if (!ost->st->language[0]) - av_strlcpy(ost->st->language, ist->st->language, - sizeof(ost->st->language)); + if ((lang=av_metadata_get(ist->st->metadata, "language", NULL, 0)) + && !av_metadata_get(ost->st->metadata, "language", NULL, 0)) + av_metadata_set(&ost->st->metadata, "language", lang->value); ost->st->disposition = ist->st->disposition; @@ -1723,9 +1746,10 @@ static int av_encode(AVFormatContext **output_files, codec->bit_rate = icodec->bit_rate; codec->extradata= icodec->extradata; codec->extradata_size= icodec->extradata_size; - if(av_q2d(icodec->time_base) > av_q2d(ist->st->time_base) && av_q2d(ist->st->time_base) < 1.0/1000) + if(av_q2d(icodec->time_base)*icodec->ticks_per_frame > av_q2d(ist->st->time_base) && av_q2d(ist->st->time_base) < 1.0/1000){ codec->time_base = icodec->time_base; - else + codec->time_base.num *= icodec->ticks_per_frame; + }else codec->time_base = ist->st->time_base; switch(codec->codec_type) { case CODEC_TYPE_AUDIO: @@ -1744,16 +1768,14 @@ static int av_encode(AVFormatContext **output_files, codec->block_align= 0; break; case CODEC_TYPE_VIDEO: - if(using_vhook) { - fprintf(stderr,"-vcodec copy and -vhook are incompatible (frames are not decoded)\n"); - av_exit(1); - } codec->pix_fmt = icodec->pix_fmt; codec->width = icodec->width; codec->height = icodec->height; codec->has_b_frames = icodec->has_b_frames; break; case CODEC_TYPE_SUBTITLE: + codec->width = icodec->width; + codec->height = icodec->height; break; default: abort(); @@ -1761,7 +1783,8 @@ static int av_encode(AVFormatContext **output_files, } else { switch(codec->codec_type) { case CODEC_TYPE_AUDIO: - if (av_fifo_init(&ost->fifo, 1024)) + ost->fifo= av_fifo_alloc(1024); + if(!ost->fifo) goto fail; ost->reformat_pair = MAKE_SFMT_PAIR(SAMPLE_FMT_NONE,SAMPLE_FMT_NONE); ost->audio_resample = codec->sample_rate != icodec->sample_rate || audio_sync_method > 1; @@ -1870,7 +1893,7 @@ static int av_encode(AVFormatContext **output_files, } if(codec->codec_type == CODEC_TYPE_VIDEO){ int size= codec->width * codec->height; - bit_buffer_size= FFMAX(bit_buffer_size, 4*size); + bit_buffer_size= FFMAX(bit_buffer_size, 6*size + 200); } } @@ -1959,6 +1982,7 @@ static int av_encode(AVFormatContext **output_files, for (i=0;ititle, in_file->title); - strcpy(out_file->author, in_file->author); - strcpy(out_file->copyright, in_file->copyright); - strcpy(out_file->comment, in_file->comment); - strcpy(out_file->album, in_file->album); - out_file->year = in_file->year; - out_file->track = in_file->track; - strcpy(out_file->genre, in_file->genre); + + mtag=NULL; + while((mtag=av_metadata_get(in_file->metadata, "", mtag, AV_METADATA_IGNORE_SUFFIX))) + av_metadata_set(&out_file->metadata, mtag->key, mtag->value); + av_metadata_conv(out_file, out_file->oformat->metadata_conv, + in_file->iformat->metadata_conv); } /* open files and write file headers */ @@ -2038,6 +2060,8 @@ static int av_encode(AVFormatContext **output_files, ost = ost_table[i]; os = output_files[ost->file_index]; ist = ist_table[ost->source_index]; + if(no_packet[ist->file_index]) + continue; if(ost->st->codec->codec_type == CODEC_TYPE_VIDEO) opts = ost->sync_opts * av_q2d(ost->st->codec->time_base); else @@ -2060,6 +2084,12 @@ static int av_encode(AVFormatContext **output_files, } /* if none, if is finished */ if (file_index < 0) { + if(no_packet_count){ + no_packet_count=0; + memset(no_packet, 0, sizeof(no_packet)); + usleep(10000); + continue; + } break; } @@ -2073,7 +2103,13 @@ static int av_encode(AVFormatContext **output_files, /* read a frame from it and output it in the fifo */ is = input_files[file_index]; - if (av_read_frame(is, &pkt) < 0) { + ret= av_read_frame(is, &pkt); + if(ret == AVERROR(EAGAIN) && strcmp(is->iformat->name, "ffm")){ + no_packet[file_index]=1; + no_packet_count++; + continue; + } + if (ret < 0) { file_table[file_index].eof_reached = 1; if (opt_shortest) break; @@ -2081,6 +2117,9 @@ static int av_encode(AVFormatContext **output_files, continue; } + no_packet_count=0; + memset(no_packet, 0, sizeof(no_packet)); + if (do_pkt_dump) { av_pkt_dump_log(NULL, AV_LOG_DEBUG, &pkt, do_hex_dump); } @@ -2197,7 +2236,7 @@ static int av_encode(AVFormatContext **output_files, fclose(ost->logfile); ost->logfile = NULL; } - av_fifo_free(&ost->fifo); /* works even if fifo is not + av_fifo_free(ost->fifo); /* works even if fifo is not initialized but set to zero */ av_free(ost->pict_tmp.data[0]); if (ost->video_resample) @@ -2290,7 +2329,7 @@ static int opt_bitrate(const char *opt, const char *arg) opt_default(opt, arg); - if (av_get_int(avctx_opts[codec_type], "b", NULL) < 1000) + if (av_get_int(avcodec_opts[codec_type], "b", NULL) < 1000) fprintf(stderr, "WARNING: The bitrate parameter is set too low. It takes bits/s as argument, not kbits/s\n"); return 0; @@ -2510,6 +2549,24 @@ static void opt_frame_aspect_ratio(const char *arg) frame_aspect_ratio = ar; } +static int opt_metadata(const char *opt, const char *arg) +{ + char *mid= strchr(arg, '='); + + if(!mid){ + fprintf(stderr, "Missing =\n"); + av_exit(1); + } + *mid++= 0; + + metadata_count++; + metadata= av_realloc(metadata, sizeof(*metadata)*metadata_count); + metadata[metadata_count-1].key = av_strdup(arg); + metadata[metadata_count-1].value= av_strdup(mid); + + return 0; +} + static void opt_qscale(const char *arg) { video_qscale = atof(arg); @@ -2528,7 +2585,7 @@ static void opt_top_field_first(const char *arg) static int opt_thread_count(const char *opt, const char *arg) { thread_count= parse_number_or_die(opt, arg, OPT_INT64, 0, INT_MAX); -#if !defined(HAVE_THREADS) +#if !HAVE_THREADS if (verbose >= 0) fprintf(stderr, "Warning: not compiled with thread support, using thread emulation\n"); #endif @@ -2601,29 +2658,6 @@ static void opt_video_tag(const char *arg) video_codec_tag= arg[0] + (arg[1]<<8) + (arg[2]<<16) + (arg[3]<<24); } -#ifdef CONFIG_VHOOK -static void add_frame_hooker(const char *arg) -{ - int argc = 0; - char *argv[64]; - int i; - char *args = av_strdup(arg); - - using_vhook = 1; - - argv[0] = strtok(args, " "); - while (argc < 62 && (argv[++argc] = strtok(NULL, " "))) { - } - - i = frame_hook_add(argc, argv); - - if (i != 0) { - fprintf(stderr, "Failed to add video hook function: %s\n", arg); - av_exit(1); - } -} -#endif - static void opt_video_codec(const char *arg) { opt_codec(&video_stream_copy, &video_codec_name, CODEC_TYPE_VIDEO, arg); @@ -2724,11 +2758,11 @@ static enum CodecID find_codec_or_die(const char *name, int type, int encoder) avcodec_find_encoder_by_name(name) : avcodec_find_decoder_by_name(name); if(!codec) { - av_log(NULL, AV_LOG_ERROR, "Unknown %s '%s'\n", codec_string, name); + fprintf(stderr, "Unknown %s '%s'\n", codec_string, name); av_exit(1); } if(codec->type != type) { - av_log(NULL, AV_LOG_ERROR, "Invalid %s type '%s'\n", codec_string, name); + fprintf(stderr, "Invalid %s type '%s'\n", codec_string, name); av_exit(1); } return codec->id; @@ -2748,7 +2782,7 @@ static void opt_input_file(const char *filename) !strcmp(filename, "/dev/stdin"); /* get default parameters from command line */ - ic = av_alloc_format_context(); + ic = avformat_alloc_context(); memset(ap, 0, sizeof(*ap)); ap->prealloced_context = 1; @@ -2772,6 +2806,7 @@ static void opt_input_file(const char *filename) ic->video_codec_id = find_codec_or_die(video_codec_name , CODEC_TYPE_VIDEO , 0); ic->audio_codec_id = find_codec_or_die(audio_codec_name , CODEC_TYPE_AUDIO , 0); ic->subtitle_codec_id= find_codec_or_die(subtitle_codec_name, CODEC_TYPE_SUBTITLE, 0); + ic->flags |= AVFMT_FLAG_NONBLOCK; /* open the input file with generic libav function */ err = av_open_input_file(&ic, filename, file_iformat, 0, ap); @@ -2820,7 +2855,7 @@ static void opt_input_file(const char *filename) enc->thread_count= thread_count; switch(enc->codec_type) { case CODEC_TYPE_AUDIO: - set_context_opts(enc, avctx_opts[CODEC_TYPE_AUDIO], AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_DECODING_PARAM); + set_context_opts(enc, avcodec_opts[CODEC_TYPE_AUDIO], AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_DECODING_PARAM); //fprintf(stderr, "\nInput Audio channels: %d", enc->channels); channel_layout = enc->channel_layout; audio_channels = enc->channels; @@ -2831,7 +2866,7 @@ static void opt_input_file(const char *filename) ic->streams[i]->discard= AVDISCARD_ALL; break; case CODEC_TYPE_VIDEO: - set_context_opts(enc, avctx_opts[CODEC_TYPE_VIDEO], AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM); + set_context_opts(enc, avcodec_opts[CODEC_TYPE_VIDEO], AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM); frame_height = enc->height; frame_width = enc->width; if(ic->streams[i]->sample_aspect_ratio.num) @@ -2960,11 +2995,11 @@ static void new_video_stream(AVFormatContext *oc) if( (video_global_header&1) || (video_global_header==0 && (oc->oformat->flags & AVFMT_GLOBALHEADER))){ video_enc->flags |= CODEC_FLAG_GLOBAL_HEADER; - avctx_opts[CODEC_TYPE_VIDEO]->flags|= CODEC_FLAG_GLOBAL_HEADER; + avcodec_opts[CODEC_TYPE_VIDEO]->flags|= CODEC_FLAG_GLOBAL_HEADER; } if(video_global_header&2){ video_enc->flags2 |= CODEC_FLAG2_LOCAL_HEADER; - avctx_opts[CODEC_TYPE_VIDEO]->flags2|= CODEC_FLAG2_LOCAL_HEADER; + avcodec_opts[CODEC_TYPE_VIDEO]->flags2|= CODEC_FLAG2_LOCAL_HEADER; } if (video_stream_copy) { @@ -2989,7 +3024,7 @@ static void new_video_stream(AVFormatContext *oc) video_enc->codec_id = codec_id; - set_context_opts(video_enc, avctx_opts[CODEC_TYPE_VIDEO], AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM); + set_context_opts(video_enc, avcodec_opts[CODEC_TYPE_VIDEO], AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM); if (codec && codec->supported_framerates && !force_fps) fps = codec->supported_framerates[av_find_nearest_q_idx(fps, codec->supported_framerates)]; @@ -3103,7 +3138,7 @@ static void new_audio_stream(AVFormatContext *oc) if (oc->oformat->flags & AVFMT_GLOBALHEADER) { audio_enc->flags |= CODEC_FLAG_GLOBAL_HEADER; - avctx_opts[CODEC_TYPE_AUDIO]->flags|= CODEC_FLAG_GLOBAL_HEADER; + avcodec_opts[CODEC_TYPE_AUDIO]->flags|= CODEC_FLAG_GLOBAL_HEADER; } if (audio_stream_copy) { st->stream_copy = 1; @@ -3111,7 +3146,7 @@ static void new_audio_stream(AVFormatContext *oc) } else { AVCodec *codec; - set_context_opts(audio_enc, avctx_opts[CODEC_TYPE_AUDIO], AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM); + set_context_opts(audio_enc, avcodec_opts[CODEC_TYPE_AUDIO], AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM); if (audio_codec_name) { codec_id = find_codec_or_die(audio_codec_name, CODEC_TYPE_AUDIO, 1); @@ -3146,7 +3181,7 @@ static void new_audio_stream(AVFormatContext *oc) audio_enc->sample_rate = audio_sample_rate; audio_enc->time_base= (AVRational){1, audio_sample_rate}; if (audio_language) { - av_strlcpy(st->language, audio_language, sizeof(st->language)); + av_metadata_set(&st->metadata, "language", audio_language); av_free(audio_language); audio_language = NULL; } @@ -3177,14 +3212,14 @@ static void new_subtitle_stream(AVFormatContext *oc) if (subtitle_stream_copy) { st->stream_copy = 1; } else { - set_context_opts(avctx_opts[CODEC_TYPE_SUBTITLE], subtitle_enc, AV_OPT_FLAG_SUBTITLE_PARAM | AV_OPT_FLAG_ENCODING_PARAM); + set_context_opts(avcodec_opts[CODEC_TYPE_SUBTITLE], subtitle_enc, AV_OPT_FLAG_SUBTITLE_PARAM | AV_OPT_FLAG_ENCODING_PARAM); subtitle_enc->codec_id = find_codec_or_die(subtitle_codec_name, CODEC_TYPE_SUBTITLE, 1); output_codecs[nb_ocodecs] = avcodec_find_encoder_by_name(subtitle_codec_name); } nb_ocodecs++; if (subtitle_language) { - av_strlcpy(st->language, subtitle_language, sizeof(st->language)); + av_metadata_set(&st->metadata, "language", subtitle_language); av_free(subtitle_language); subtitle_language = NULL; } @@ -3237,7 +3272,7 @@ static void opt_output_file(const char *filename) if (!strcmp(filename, "-")) filename = "pipe:"; - oc = av_alloc_format_context(); + oc = avformat_alloc_context(); if (!file_oformat) { file_oformat = guess_format(NULL, filename, NULL); @@ -3303,18 +3338,11 @@ static void opt_output_file(const char *filename) oc->timestamp = rec_timestamp; - if (str_title) - av_strlcpy(oc->title, str_title, sizeof(oc->title)); - if (str_author) - av_strlcpy(oc->author, str_author, sizeof(oc->author)); - if (str_copyright) - av_strlcpy(oc->copyright, str_copyright, sizeof(oc->copyright)); - if (str_comment) - av_strlcpy(oc->comment, str_comment, sizeof(oc->comment)); - if (str_album) - av_strlcpy(oc->album, str_album, sizeof(oc->album)); - if (str_genre) - av_strlcpy(oc->genre, str_genre, sizeof(oc->genre)); + for(; metadata_count>0; metadata_count--){ + av_metadata_set(&oc->metadata, metadata[metadata_count-1].key, + metadata[metadata_count-1].value); + } + av_metadata_conv(oc, oc->oformat->metadata_conv, NULL); } output_files[nb_output_files++] = oc; @@ -3369,6 +3397,7 @@ static void opt_output_file(const char *filename) oc->preload= (int)(mux_preload*AV_TIME_BASE); oc->max_delay= (int)(mux_max_delay*AV_TIME_BASE); oc->loop_output = loop_output; + oc->flags |= AVFMT_FLAG_NONBLOCK; set_context_opts(oc, avformat_opts, AV_OPT_FLAG_ENCODING_PARAM); @@ -3391,12 +3420,12 @@ static void opt_pass(const char *pass_str) static int64_t getutime(void) { -#ifdef HAVE_GETRUSAGE +#if HAVE_GETRUSAGE struct rusage rusage; getrusage(RUSAGE_SELF, &rusage); return (rusage.ru_utime.tv_sec * 1000000LL) + rusage.ru_utime.tv_usec; -#elif defined(HAVE_GETPROCESSTIMES) +#elif HAVE_GETPROCESSTIMES HANDLE proc; FILETIME c, e, k, u; proc = GetCurrentProcess(); @@ -3475,7 +3504,7 @@ static void show_help(void) OPT_GRAB, OPT_GRAB); printf("\n"); - av_opt_show(avctx_opts[0], NULL); + av_opt_show(avcodec_opts[0], NULL); printf("\n"); av_opt_show(avformat_opts, NULL); printf("\n"); @@ -3670,25 +3699,24 @@ static int opt_preset(const char *opt, const char *arg) FILE *f=NULL; char filename[1000], tmp[1000], tmp2[1000], line[1000]; int i; - const char *base[3]= { getenv("HOME"), - "/usr/local/share", - "/usr/share", + const char *base[2]= { getenv("HOME"), + FFMPEG_DATADIR, }; - for(i=!base[0]; i<3 && !f; i++){ - snprintf(filename, sizeof(filename), "%s/%sffmpeg/%s.ffpreset", base[i], i ? "" : ".", arg); + for(i=!base[0]; i<2 && !f; i++){ + snprintf(filename, sizeof(filename), "%s%s/%s.ffpreset", base[i], i ? "" : "/.ffmpeg", arg); f= fopen(filename, "r"); if(!f){ char *codec_name= *opt == 'v' ? video_codec_name : *opt == 'a' ? audio_codec_name : subtitle_codec_name; - snprintf(filename, sizeof(filename), "%s/%sffmpeg/%s-%s.ffpreset", base[i], i ? "" : ".", codec_name, arg); + snprintf(filename, sizeof(filename), "%s%s/%s-%s.ffpreset", base[i], i ? "" : "/.ffmpeg", codec_name, arg); f= fopen(filename, "r"); } } if(!f && ((arg[0]=='.' && arg[1]=='/') || arg[0]=='/' || is_dos_path(arg))){ - snprintf(filename, sizeof(filename), arg); + av_strlcpy(filename, arg, sizeof(filename)); f= fopen(filename, "r"); } @@ -3739,13 +3767,8 @@ static const OptionDef options[] = { { "ss", OPT_FUNC2 | HAS_ARG, {(void*)opt_start_time}, "set the start time offset", "time_off" }, { "itsoffset", OPT_FUNC2 | HAS_ARG, {(void*)opt_input_ts_offset}, "set the input ts offset", "time_off" }, { "itsscale", HAS_ARG, {(void*)opt_input_ts_scale}, "set the input ts scale", "stream:scale" }, - { "title", HAS_ARG | OPT_STRING, {(void*)&str_title}, "set the title", "string" }, - { "timestamp", OPT_FUNC2 | HAS_ARG, {(void*)&opt_rec_timestamp}, "set the timestamp", "time" }, - { "author", HAS_ARG | OPT_STRING, {(void*)&str_author}, "set the author", "string" }, - { "copyright", HAS_ARG | OPT_STRING, {(void*)&str_copyright}, "set the copyright", "string" }, - { "comment", HAS_ARG | OPT_STRING, {(void*)&str_comment}, "set the comment", "string" }, - { "genre", HAS_ARG | OPT_STRING, {(void*)&str_genre}, "set the genre", "string" }, - { "album", HAS_ARG | OPT_STRING, {(void*)&str_album}, "set the album", "string" }, + { "timestamp", OPT_FUNC2 | HAS_ARG, {(void*)&opt_rec_timestamp}, "set the timestamp ('now' to set the current time)", "time" }, + { "metadata", OPT_FUNC2 | HAS_ARG, {(void*)&opt_metadata}, "add metadata", "string=string" }, { "dframes", OPT_INT | HAS_ARG, {(void*)&max_frames[CODEC_TYPE_DATA]}, "set the number of data frames to record", "number" }, { "benchmark", OPT_BOOL | OPT_EXPERT, {(void*)&do_benchmark}, "add timings for benchmarking" }, @@ -3803,9 +3826,6 @@ static const OptionDef options[] = { { "psnr", OPT_BOOL | OPT_EXPERT | OPT_VIDEO, {(void*)&do_psnr}, "calculate PSNR of compressed frames" }, { "vstats", OPT_EXPERT | OPT_VIDEO, {(void*)&opt_vstats}, "dump video coding statistics to file" }, { "vstats_file", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_vstats_file}, "dump video coding statistics to file", "file" }, -#ifdef CONFIG_VHOOK - { "vhook", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)add_frame_hooker}, "insert video processing module", "module" }, -#endif { "intra_matrix", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_intra_matrix}, "specify intra matrix coeffs", "matrix" }, { "inter_matrix", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_inter_matrix}, "specify inter matrix coeffs", "matrix" }, { "top", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_top_field_first}, "top=1/bottom=0/auto=-1 field first", "" }, @@ -3869,9 +3889,9 @@ int main(int argc, char **argv) url_set_interrupt_cb(decode_interrupt_cb); for(i=0; i