X-Git-Url: http://git.cinelerra-gg.org/git/?a=blobdiff_plain;f=cinelerra-5.1%2Fcinelerra%2Fffmpeg.C;h=6c3789e84f5660672321a37837e72f0bddc56291;hb=318256a48938064b695268d03396977739ef4724;hp=64acfe2bdbbd4a1026016eb65f8c1a0ddce033fa;hpb=190b4810ec184c74ceab3fcd6faf09a91c92c53c;p=goodguy%2Fhistory.git diff --git a/cinelerra-5.1/cinelerra/ffmpeg.C b/cinelerra-5.1/cinelerra/ffmpeg.C index 64acfe2b..6c3789e8 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; @@ -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; } } @@ -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) { @@ -834,6 +838,9 @@ AVPixelFormat FFVideoConvert::color_model_to_pix_fmt(int color_model) 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; @@ -855,6 +862,9 @@ int FFVideoConvert::pix_fmt_to_color_model(AVPixelFormat pix_fmt) 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; @@ -1992,8 +2047,8 @@ void FFMPEG::stop_muxer() if( running() ) { done = 1; mux_lock->unlock(); - join(); } + join(); } void FFMPEG::flow_off() @@ -2502,7 +2557,7 @@ printf("audio%d pad %ld %ld (%ld)\n", aud->idx, pos, aud->curr_pos, pos-aud->cur int got_frame = 0; int ret = aud->decode_frame(&pkt, frame, got_frame); if( ret <= 0 ) break; - if( got_frame ) { + if( got_frame && frame->channels == nch ) { float *samples; int len = aud->get_samples(samples, &frame->extended_data[0], frame->nb_samples); @@ -2523,7 +2578,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;