X-Git-Url: http://git.cinelerra-gg.org/git/?p=goodguy%2Fhistory.git;a=blobdiff_plain;f=cinelerra-5.1%2Fcinelerra%2Fffmpeg.C;h=16c6409b9653154c54c5d91d20736a2d549ad834;hp=ccf80afcbce0e94590c05696b9a165a73d7e1ec1;hb=21c2e6b36d6a96c2f662a89459d607b5a387f4eb;hpb=788dfe4aae1aef521caddcc68dec7369a996dce7 diff --git a/cinelerra-5.1/cinelerra/ffmpeg.C b/cinelerra-5.1/cinelerra/ffmpeg.C index ccf80afc..16c6409b 100644 --- a/cinelerra-5.1/cinelerra/ffmpeg.C +++ b/cinelerra-5.1/cinelerra/ffmpeg.C @@ -47,21 +47,15 @@ static void ff_err(int ret, const char *fmt, ...) fprintf(stderr,_("%s err: %s\n"),msg, errmsg); } -FFPacket::FFPacket() -{ - init(); -} - -FFPacket::~FFPacket() -{ - av_packet_unref(&pkt); -} - void FFPacket::init() { av_init_packet(&pkt); pkt.data = 0; pkt.size = 0; } +void FFPacket::finit() +{ + av_packet_unref(&pkt); +} FFrame::FFrame(FFStream *fst) { @@ -246,7 +240,6 @@ FFStream::FFStream(FFMPEG *ffmpeg, AVStream *st, int fidx) nudge = AV_NOPTS_VALUE; seek_pos = curr_pos = 0; seeked = 1; eof = 0; - index_markers = 0; reading = writing = 0; flushed = 0; need_packet = 1; @@ -321,10 +314,10 @@ int FFStream::decode_activate() if( ret >= 0 ) reading = 1; else - eprintf("FFStream::decode_activate: open decoder failed\n"); + eprintf(_("open decoder failed\n")); } else - eprintf("FFStream::decode_activate: can't clone input file\n"); + eprintf(_("can't clone input file\n")); av_dict_free(&copts); ff_unlock(); } @@ -391,7 +384,7 @@ int FFStream::load_filter(AVFrame *frame) frame, AV_BUFFERSRC_FLAG_KEEP_REF); if( ret < 0 ) { av_frame_unref(frame); - eprintf("FFStream::load_filter: av_buffersrc_add_frame_flags failed\n"); + eprintf(_("av_buffersrc_add_frame_flags failed\n")); } return ret; } @@ -449,10 +442,11 @@ int FFStream::flush() int FFStream::seek(int64_t no, double rate) { - if( no < 0 ) no = 0; + int64_t tstmp = -INT64_MAX+1; // default ffmpeg native seek int npkts = 1; int64_t pos = no, plmt = -1; + IndexMarks *index_markers = get_markers(); if( index_markers && index_markers->size() > 1 ) { IndexMarks &marks = *index_markers; int i = marks.find(pos); @@ -461,27 +455,30 @@ int FFStream::seek(int64_t no, double rate) if( no-n < 30*rate ) { if( n < 0 ) n = 0; pos = n; - if( ++i < marks.size() ) plmt = marks[i].pos; + if( i < marks.size() ) plmt = marks[i].pos; npkts = MAX_RETRY; } } - double secs = pos / rate; - int64_t pkt_ts, tstmp = secs * st->time_base.den / st->time_base.num; - if( nudge != AV_NOPTS_VALUE ) tstmp += nudge; + if( pos > 0 ) { + double secs = pos / rate; + tstmp = secs * st->time_base.den / st->time_base.num; + if( nudge != AV_NOPTS_VALUE ) tstmp += nudge; + } int ret = avformat_seek_file(fmt_ctx, st->index, -INT64_MAX, tstmp, INT64_MAX, AVSEEK_FLAG_ANY); if( ret >= 0 ) { avcodec_flush_buffers(st->codec); + ipkt.finit(); ipkt.init(); need_packet = 0; flushed = 0; seeked = 1; st_eof(0); // read up to retry packets, limited to npkts in stream, and not past pkt.pos plmt - for( int retry=MAX_RETRY; ret>=0 && --retry>=0; ) { + for(;;) { if( read_packet() <= 0 ) { ret = -1; break; } if( plmt >= 0 && ipkt->pos >= plmt ) break; if( ipkt->stream_index != st->index ) continue; if( --npkts <= 0 ) break; - if( (pkt_ts=ipkt->dts) == AV_NOPTS_VALUE && - (pkt_ts=ipkt->pts) == AV_NOPTS_VALUE ) continue; + int64_t pkt_ts = ipkt->dts != AV_NOPTS_VALUE ? ipkt->dts : ipkt->pts; + if( pkt_ts == AV_NOPTS_VALUE ) continue; if( pkt_ts >= tstmp ) break; } } @@ -529,7 +526,7 @@ int FFAudioStream::get_samples(float *&samples, uint8_t **data, int len) { samples = *(float **)data; if( resample_context ) { - if( len > aud_bfr_sz ) { + if( len > aud_bfr_sz ) { delete [] aud_bfr; aud_bfr = 0; } @@ -706,11 +703,18 @@ int FFAudioStream::encode_frame(AVPacket *pkt, AVFrame *frame, int &got_packet) void FFAudioStream::load_markers() { IndexState *index_state = ffmpeg->file_base->asset->index_state; - if( index_state->marker_status == MARKERS_NOTTESTED ) return; if( !index_state || idx >= index_state->audio_markers.size() ) return; + if( index_state->marker_status == MARKERS_NOTTESTED ) return; FFStream::load_markers(*index_state->audio_markers[idx], sample_rate); } +IndexMarks *FFAudioStream::get_markers() +{ + IndexState *index_state = ffmpeg->file_base->asset->index_state; + if( !index_state || idx >= index_state->audio_markers.size() ) return 0; + return index_state->audio_markers[idx]; +} + FFVideoStream::FFVideoStream(FFMPEG *ffmpeg, AVStream *strm, int idx, int fidx) : FFStream(ffmpeg, strm, fidx) { @@ -828,12 +832,15 @@ int FFVideoStream::encode_frame(AVPacket *pkt, AVFrame *frame, int &got_packet) AVPixelFormat FFVideoConvert::color_model_to_pix_fmt(int color_model) { - switch( color_model ) { + switch( color_model ) { case BC_YUV422: return AV_PIX_FMT_YUYV422; case BC_RGB888: return AV_PIX_FMT_RGB24; case BC_RGBA8888: return AV_PIX_FMT_RGBA; case BC_BGR8888: return AV_PIX_FMT_BGR0; case BC_BGR888: return AV_PIX_FMT_BGR24; + case BC_ARGB8888: return AV_PIX_FMT_ARGB; + case BC_ABGR8888: return AV_PIX_FMT_ABGR; + case BC_RGB8: return AV_PIX_FMT_RGB8; case BC_YUV420P: return AV_PIX_FMT_YUV420P; case BC_YUV422P: return AV_PIX_FMT_YUV422P; case BC_YUV444P: return AV_PIX_FMT_YUV444P; @@ -849,12 +856,15 @@ AVPixelFormat FFVideoConvert::color_model_to_pix_fmt(int color_model) int FFVideoConvert::pix_fmt_to_color_model(AVPixelFormat pix_fmt) { - switch (pix_fmt) { + switch (pix_fmt) { case AV_PIX_FMT_YUYV422: return BC_YUV422; case AV_PIX_FMT_RGB24: return BC_RGB888; case AV_PIX_FMT_RGBA: return BC_RGBA8888; case AV_PIX_FMT_BGR0: return BC_BGR8888; case AV_PIX_FMT_BGR24: return BC_BGR888; + case AV_PIX_FMT_ARGB: return BC_ARGB8888; + case AV_PIX_FMT_ABGR: return BC_ABGR8888; + case AV_PIX_FMT_RGB8: return BC_RGB8; case AV_PIX_FMT_YUV420P: return BC_YUV420P; case AV_PIX_FMT_YUV422P: return BC_YUV422P; case AV_PIX_FMT_YUV444P: return BC_YUV444P; @@ -865,12 +875,26 @@ int FFVideoConvert::pix_fmt_to_color_model(AVPixelFormat pix_fmt) default: break; } - return BC_TRANSPARENCY; + return -1; } int FFVideoConvert::convert_picture_vframe(VFrame *frame, AVFrame *ip, AVPixelFormat ifmt, int iw, int ih) { + // try bc_xfer methods + int imodel = pix_fmt_to_color_model(ifmt); + if( imodel >= 0 ) { + long y_ofs = 0, u_ofs = 0, v_ofs = 0; + uint8_t *data = ip->data[0]; + if( BC_CModels::is_yuv(imodel) ) { + u_ofs = ip->data[1] - data; + v_ofs = ip->data[2] - data; + } + VFrame iframe(data, -1, y_ofs, u_ofs, v_ofs, iw, ih, imodel, ip->linesize[0]); + frame->transfer_from(&iframe); + return 0; + } + // try sws methods AVFrame opic; int cmodel = frame->get_color_model(); AVPixelFormat ofmt = color_model_to_pix_fmt(cmodel); @@ -1024,10 +1048,17 @@ int FFVideoConvert::transfer_pixfmt(VFrame *frame, void FFVideoStream::load_markers() { IndexState *index_state = ffmpeg->file_base->asset->index_state; - if( idx >= index_state->video_markers.size() ) return; + if( !index_state || idx >= index_state->video_markers.size() ) return; FFStream::load_markers(*index_state->video_markers[idx], frame_rate); } +IndexMarks *FFVideoStream::get_markers() +{ + IndexState *index_state = ffmpeg->file_base->asset->index_state; + if( !index_state || idx >= index_state->video_markers.size() ) return 0; + return !index_state ? 0 : index_state->video_markers[idx]; +} + FFMPEG::FFMPEG(FileBase *file_base) { @@ -1123,13 +1154,15 @@ AVRational FFMPEG::to_time_base(int sample_rate) void FFMPEG::set_option_path(char *path, const char *fmt, ...) { - get_exe_path(path); - strcat(path, "/ffmpeg/"); + char *ep = path + BCTEXTLEN-1; + strncpy(path, File::get_cindat_path(), ep-path); + strncat(path, "/ffmpeg/", ep-path); path += strlen(path); va_list ap; va_start(ap, fmt); - vsprintf(path, fmt, ap); + path += vsnprintf(path, ep-path, fmt, ap); va_end(ap); + *path = 0; } void FFMPEG::get_option_path(char *path, const char *type, const char *spec) @@ -1140,7 +1173,7 @@ void FFMPEG::get_option_path(char *path, const char *type, const char *spec) set_option_path(path, "%s/%s", type, spec); } -int FFMPEG::get_format(char *format, const char *path, char *spec) +int FFMPEG::get_format(char *format, const char *path, const char *spec) { char option_path[BCTEXTLEN], line[BCTEXTLEN], codec[BCTEXTLEN]; get_option_path(option_path, path, spec); @@ -1156,6 +1189,28 @@ int FFMPEG::get_format(char *format, const char *path, char *spec) return ret; } +int FFMPEG::get_codec(char *codec, const char *path, const char *spec) +{ + char option_path[BCTEXTLEN], line[BCTEXTLEN], format[BCTEXTLEN]; + get_option_path(option_path, path, spec); + FILE *fp = fopen(option_path,"r"); + if( !fp ) return 1; + int ret = 0; + if( !fgets(line, sizeof(line), fp) ) ret = 1; + fclose(fp); + if( !ret ) { + line[sizeof(line)-1] = 0; + ret = scan_option_line(line, format, codec); + } + if( !ret ) { + char *vp = codec, *ep = vp+BCTEXTLEN-1; + while( vp < ep && *vp && *vp != '|' ) ++vp; + if( *vp == '|' ) --vp; + while( vp > codec && (*vp==' ' || *vp=='\t') ) *vp-- = 0; + } + return ret; +} + int FFMPEG::get_file_format() { int ret = 0; @@ -1235,12 +1290,11 @@ int FFMPEG::get_encoder(const char *options, { FILE *fp = fopen(options,"r"); if( !fp ) { - eprintf("FFMPEG::get_encoder: options open failed %s\n",options); + eprintf(_("options open failed %s\n"),options); return 1; } if( get_encoder(fp, format, codec, bsfilter, bsargs) ) - eprintf(_("FFMPEG::get_encoder:" - " err: format/codec not found %s\n"), options); + eprintf(_("format/codec not found %s\n"), options); fclose(fp); return 0; } @@ -1292,8 +1346,7 @@ int FFMPEG::read_options(FILE *fp, const char *options, AVDictionary *&opts) if( line[0] == '\n' ) continue; char key[BCSTRLEN], val[BCTEXTLEN]; if( scan_option_line(line, key, val) ) { - eprintf(_("FFMPEG::read_options:" - " err reading %s: line %d\n"), options, no); + eprintf(_("err reading %s: line %d\n"), options, no); ret = 1; } if( !ret ) { @@ -1361,7 +1414,7 @@ double FFMPEG::to_secs(int64_t time, AVRational time_base) { double base_time = time == AV_NOPTS_VALUE ? 0 : av_rescale_q(time, time_base, AV_TIME_BASE_Q); - return base_time / AV_TIME_BASE; + return base_time / AV_TIME_BASE; } int FFMPEG::info(char *text, int len) @@ -1486,8 +1539,7 @@ int FFMPEG::open_decoder() { struct stat st; if( stat(fmt_ctx->filename, &st) < 0 ) { - eprintf("FFMPEG::open_decoder: can't stat file: %s\n", - fmt_ctx->filename); + eprintf(_("can't stat file: %s\n"), fmt_ctx->filename); return 1; } @@ -1579,24 +1631,24 @@ int FFMPEG::init_encoder(const char *filename) int fd = ::open(filename,O_WRONLY); if( fd < 0 ) fd = open(filename,O_WRONLY+O_CREAT,0666); if( fd < 0 ) { - eprintf("FFMPEG::init_encoder: bad file path: %s\n", filename); + eprintf(_("bad file path: %s\n"), filename); return 1; } ::close(fd); int ret = get_file_format(); if( ret > 0 ) { - eprintf("FFMPEG::init_encoder: bad file format: %s\n", filename); + eprintf(_("bad file format: %s\n"), filename); return 1; } if( ret < 0 ) { - eprintf("FFMPEG::init_encoder: mismatch audio/video file format: %s\n", filename); + eprintf(_("mismatch audio/video file format: %s\n"), filename); return 1; } ff_lock("FFMPEG::init_encoder"); av_register_all(); avformat_alloc_output_context2(&fmt_ctx, 0, file_format, filename); if( !fmt_ctx ) { - eprintf("FFMPEG::init_encoder: failed: %s\n", filename); + eprintf(_("failed: %s\n"), filename); ret = 1; } if( !ret ) { @@ -1621,8 +1673,7 @@ int FFMPEG::open_encoder(const char *type, const char *spec) char format_name[BCSTRLEN], codec_name[BCTEXTLEN]; char bsfilter[BCSTRLEN], bsargs[BCTEXTLEN]; if( get_encoder(option_path, format_name, codec_name, bsfilter, bsargs) ) { - eprintf("FFMPEG::open_encoder: get_encoder failed %s:%s\n", - option_path, filename); + eprintf(_("get_encoder failed %s:%s\n"), option_path, filename); return 1; } @@ -1638,40 +1689,35 @@ int FFMPEG::open_encoder(const char *type, const char *spec) const AVCodecDescriptor *codec_desc = 0; AVCodec *codec = avcodec_find_encoder_by_name(codec_name); if( !codec ) { - eprintf("FFMPEG::open_encoder: cant find codec %s:%s\n", - codec_name, filename); + eprintf(_("cant find codec %s:%s\n"), codec_name, filename); ret = 1; } if( !ret ) { codec_desc = avcodec_descriptor_get(codec->id); if( !codec_desc ) { - eprintf("FFMPEG::open_encoder: unknown codec %s:%s\n", - codec_name, filename); + eprintf(_("unknown codec %s:%s\n"), codec_name, filename); ret = 1; } } if( !ret ) { st = avformat_new_stream(fmt_ctx, 0); if( !st ) { - eprintf("FFMPEG::open_encoder: cant create stream %s:%s\n", - codec_name, filename); + eprintf(_("cant create stream %s:%s\n"), codec_name, filename); ret = 1; } - } + } if( !ret ) { AVCodecContext *ctx = st->codec; switch( codec_desc->type ) { case AVMEDIA_TYPE_AUDIO: { if( has_audio ) { - eprintf("FFMPEG::open_encoder: duplicate audio %s:%s\n", - codec_name, filename); + eprintf(_("duplicate audio %s:%s\n"), codec_name, filename); ret = 1; break; } has_audio = 1; if( scan_options(asset->ff_audio_options, sopts, st) ) { - eprintf("FFMPEG::open_encoder: bad audio options %s:%s\n", - codec_name, filename); + eprintf(_("bad audio options %s:%s\n"), codec_name, filename); ret = 1; break; } @@ -1692,8 +1738,7 @@ int FFMPEG::open_encoder(const char *type, const char *spec) ctx->channel_layout = av_get_default_channel_layout(ctx->channels); ctx->sample_rate = check_sample_rate(codec, asset->sample_rate); if( !ctx->sample_rate ) { - eprintf("FFMPEG::open_encoder:" - " check_sample_rate failed %s\n", filename); + eprintf(_("check_sample_rate failed %s\n"), filename); ret = 1; break; } @@ -1709,15 +1754,13 @@ int FFMPEG::open_encoder(const char *type, const char *spec) break; } case AVMEDIA_TYPE_VIDEO: { if( has_video ) { - eprintf("FFMPEG::open_encoder: duplicate video %s:%s\n", - codec_name, filename); + eprintf(_("duplicate video %s:%s\n"), codec_name, filename); ret = 1; break; } has_video = 1; if( scan_options(asset->ff_video_options, sopts, st) ) { - eprintf("FFMPEG::open_encoder: bad video options %s:%s\n", - codec_name, filename); + eprintf(_("bad video options %s:%s\n"), codec_name, filename); ret = 1; break; } @@ -1754,8 +1797,7 @@ int FFMPEG::open_encoder(const char *type, const char *spec) ctx->pix_fmt = codec->pix_fmts ? codec->pix_fmts[0] : AV_PIX_FMT_YUV420P; AVRational frame_rate = check_frame_rate(codec, vid->frame_rate); if( !frame_rate.num || !frame_rate.den ) { - eprintf("FFMPEG::open_encoder:" - " check_frame_rate failed %s\n", filename); + eprintf(_("check_frame_rate failed %s\n"), filename); ret = 1; break; } @@ -1764,8 +1806,7 @@ int FFMPEG::open_encoder(const char *type, const char *spec) vid->writing = -1; break; } default: - eprintf("FFMPEG::open_encoder: not audio/video, %s:%s\n", - codec_name, filename); + eprintf(_("not audio/video, %s:%s\n"), codec_name, filename); ret = 1; } } @@ -1776,8 +1817,7 @@ int FFMPEG::open_encoder(const char *type, const char *spec) ret = avcodec_open2(st->codec, codec, &sopts); if( ret < 0 ) { ff_err(ret,"FFMPEG::open_encoder"); - eprintf("FFMPEG::open_encoder: open failed %s:%s\n", - codec_name, filename); + eprintf(_("open failed %s:%s\n"), codec_name, filename); ret = 1; } else @@ -1992,8 +2032,8 @@ void FFMPEG::stop_muxer() if( running() ) { done = 1; mux_lock->unlock(); - join(); } + join(); } void FFMPEG::flow_off() @@ -2124,7 +2164,7 @@ const char* FFMPEG::ff_audio_format(int stream) AVStream *st = ffaudio[stream]->st; AVCodecID id = st->codec->codec_id; const AVCodecDescriptor *desc = avcodec_descriptor_get(id); - return desc ? desc->name : "Unknown"; + return desc ? desc->name : _("Unknown"); } int FFMPEG::ff_audio_pid(int stream) @@ -2234,7 +2274,7 @@ const char* FFMPEG::ff_video_format(int stream) AVStream *st = ffvideo[stream]->st; AVCodecID id = st->codec->codec_id; const AVCodecDescriptor *desc = avcodec_descriptor_get(id); - return desc ? desc->name : "Unknown"; + return desc ? desc->name : _("Unknown"); } double FFMPEG::ff_frame_rate(int stream) @@ -2411,7 +2451,8 @@ int FFMPEG::scan(IndexState *index_state, int64_t *scan_position, int *canceled) av_init_packet(&pkt); AVFrame *frame = av_frame_alloc(); if( !frame ) { - fprintf(stderr, "FFMPEG::scan: av_frame_alloc failed\n"); + fprintf(stderr,"FFMPEG::scan: "); + fprintf(stderr,_("av_frame_alloc failed\n")); return -1; } @@ -2424,8 +2465,10 @@ int FFMPEG::scan(IndexState *index_state, int64_t *scan_position, int *canceled) AVStream *st = fmt_ctx->streams[i]; AVCodecID codec_id = st->codec->codec_id; AVCodec *decoder = avcodec_find_decoder(codec_id); - if( avcodec_open2(st->codec, decoder, &copts) < 0 ) - fprintf(stderr, "FFMPEG::scan: codec open failed\n"); + if( avcodec_open2(st->codec, decoder, &copts) < 0 ) { + fprintf(stderr,"FFMPEG::scan: "); + fprintf(stderr,_("codec open failed\n")); + } av_dict_free(&copts); } int errs = 0; @@ -2437,7 +2480,7 @@ int FFMPEG::scan(IndexState *index_state, int64_t *scan_position, int *canceled) if( ret < 0 ) { if( ret == AVERROR_EOF ) break; if( ++errs > 100 ) { - ff_err(ret, "over 100 read_frame errs\n"); + ff_err(ret,_("over 100 read_frame errs\n")); break; } continue; @@ -2495,7 +2538,7 @@ int FFMPEG::scan(IndexState *index_state, int64_t *scan_position, int *canceled) int64_t pos = index_state->pos(ch); if( pos != aud->curr_pos ) { if( abs(pos-aud->curr_pos) > 1 ) -printf("audio%d pad %ld %ld (%ld)\n", aud->idx, pos, aud->curr_pos, pos-aud->curr_pos); +printf("audio%d pad %jd %jd (%jd)\n", aud->idx, pos, aud->curr_pos, pos-aud->curr_pos); index_state->pad_data(ch, nch, aud->curr_pos); } av_frame_unref(frame); @@ -2523,7 +2566,6 @@ printf("audio%d pad %ld %ld (%ld)\n", aud->idx, pos, aud->curr_pos, pos-aud->cur void FFStream::load_markers(IndexMarks &marks, double rate) { - index_markers = &marks; int in = 0; int64_t sz = marks.size(); int max_entries = fmt_ctx->max_index_size / sizeof(AVIndexEntry) - 1;