So, I grep'ed ffmpeg-4.3 sources and apparently thise falgs consumed by few 
encoders outside of mpeg2/4:

guest@slax:/dev/shm/cinelerra/cinelerra-5.1/cinelerra$ grep 
'AV_CODEC_FLAG_INTERLACED_DCT' ../thirdparty/ffmpeg-4.3/libav
libavcodec/    libavdevice/   libavfilter/   libavformat/   libavresample/ 
libavutil/
guest@slax:/dev/shm/cinelerra/cinelerra-5.1/cinelerra$ grep 
'AV_CODEC_FLAG_INTERLACED_DCT' ../thirdparty/ffmpeg-4.3/libavcodec/*.c
../thirdparty/ffmpeg-4.3/libavcodec/cuviddec.c:        avctx->flags |= 
AV_CODEC_FLAG_INTERLACED_DCT;
../thirdparty/ffmpeg-4.3/libavcodec/cuviddec.c:        avctx->flags &= 
~AV_CODEC_FLAG_INTERLACED_DCT;
../thirdparty/ffmpeg-4.3/libavcodec/dnxhddata.c:            interlaced == 
!!(avctx->flags & AV_CODEC_FLAG_INTERLACED_DCT) &&
../thirdparty/ffmpeg-4.3/libavcodec/dnxhdenc.c:    if (avctx->flags & 
AV_CODEC_FLAG_INTERLACED_DCT) {
../thirdparty/ffmpeg-4.3/libavcodec/dvenc.c:    if (s->avctx->flags & 
AV_CODEC_FLAG_INTERLACED_DCT) {
../thirdparty/ffmpeg-4.3/libavcodec/libx264.c:    x4->params.b_interlaced   = 
avctx->flags & AV_CODEC_FLAG_INTERLACED_DCT;
../thirdparty/ffmpeg-4.3/libavcodec/libxavs.c:    x4->params.b_interlaced   = 
avctx->flags & AV_CODEC_FLAG_INTERLACED_DCT;
../thirdparty/ffmpeg-4.3/libavcodec/mpegvideo_enc.c:    if ((s->avctx->flags & 
(AV_CODEC_FLAG_INTERLACED_DCT | AV_CODEC_FLAG_INTERLACED_ME)) &&
../thirdparty/ffmpeg-4.3/libavcodec/mpegvideo_enc.c:    s->progressive_sequence 
= !(avctx->flags & (AV_CODEC_FLAG_INTERLACED_DCT |
../thirdparty/ffmpeg-4.3/libavcodec/mpegvideo_enc.c:        if (s->avctx->flags 
& AV_CODEC_FLAG_INTERLACED_DCT) {
../thirdparty/ffmpeg-4.3/libavcodec/mpegvideo_enc.c:        if (s->avctx->flags 
& AV_CODEC_FLAG_INTERLACED_DCT) {
../thirdparty/ffmpeg-4.3/libavcodec/nvenc.c:    if (ret < 1 && avctx->flags & 
AV_CODEC_FLAG_INTERLACED_DCT) {
../thirdparty/ffmpeg-4.3/libavcodec/nvenc.c:    if (avctx->flags & 
AV_CODEC_FLAG_INTERLACED_DCT) {
../thirdparty/ffmpeg-4.3/libavcodec/nvenc.c:        if (avctx->flags & 
AV_CODEC_FLAG_INTERLACED_DCT) {
../thirdparty/ffmpeg-4.3/libavcodec/pngenc.c:    s->is_progressive = 
!!(avctx->flags & AV_CODEC_FLAG_INTERLACED_DCT);
../thirdparty/ffmpeg-4.3/libavcodec/proresenc_anatoliy.c:    ctx->is_interlaced 
= !!(avctx->flags & AV_CODEC_FLAG_INTERLACED_DCT);
../thirdparty/ffmpeg-4.3/libavcodec/proresenc_kostya.c:    if (avctx->flags & 
AV_CODEC_FLAG_INTERLACED_DCT)
../thirdparty/ffmpeg-4.3/libavcodec/proresenc_kostya.c:    int interlaced = 
!!(avctx->flags & AV_CODEC_FLAG_INTERLACED_DCT);
../thirdparty/ffmpeg-4.3/libavcodec/qsvenc.c:    if (avctx->flags & 
AV_CODEC_FLAG_INTERLACED_DCT) {
guest@slax:/dev/shm/cinelerra/cinelerra-5.1/cinelerra$ grep 
'AV_CODEC_FLAG_INTERLACED_ME' ../thirdparty/ffmpeg-4.3/libavcodec/*.c
../thirdparty/ffmpeg-4.3/libavcodec/huffyuvenc.c:    s->interlaced = 
avctx->flags & AV_CODEC_FLAG_INTERLACED_ME ? 1 : 0;
../thirdparty/ffmpeg-4.3/libavcodec/motion_est.c:        if ((s->avctx->flags & 
AV_CODEC_FLAG_INTERLACED_ME)
../thirdparty/ffmpeg-4.3/libavcodec/motion_est.c:        if ((s->avctx->flags & 
AV_CODEC_FLAG_INTERLACED_ME)
../thirdparty/ffmpeg-4.3/libavcodec/motion_est.c:    if (s->avctx->flags & 
AV_CODEC_FLAG_INTERLACED_ME) {
../thirdparty/ffmpeg-4.3/libavcodec/mpegvideo.c:        (s->avctx->flags & 
AV_CODEC_FLAG_INTERLACED_ME)) {
../thirdparty/ffmpeg-4.3/libavcodec/mpegvideo_enc.c:    if ((s->avctx->flags & 
(AV_CODEC_FLAG_INTERLACED_DCT | AV_CODEC_FLAG_INTERLACED_ME)) &&
../thirdparty/ffmpeg-4.3/libavcodec/mpegvideo_enc.c:                            
                    AV_CODEC_FLAG_INTERLACED_ME) ||
../thirdparty/ffmpeg-4.3/libavcodec/mpegvideo_enc.c:            if 
(s->avctx->flags & AV_CODEC_FLAG_INTERLACED_ME) {
../thirdparty/ffmpeg-4.3/libavcodec/mpegvideo_enc.c:            if 
(s->avctx->flags & AV_CODEC_FLAG_INTERLACED_ME) {
../thirdparty/ffmpeg-4.3/libavcodec/mpegvideo_enc.c:            if 
(s->avctx->flags & AV_CODEC_FLAG_INTERLACED_ME) {


So, reworked this section again ... basically only excluding mjpeg codec case 
from setting those flags, instead of whilelisting mpeg2/4 only

Strangely ffv1/avi shows interlace (with my patch) if source was Top Field 
First and not showing it if source was Bottom Field First ..:/

dv file re-encoded as dv_ntsc.avi shows bff correctly, it seems.
mp4 container with h264 also gets it right now ....
mpeg2 works (but not sure if field order correct or now ..I'm confused by 
ffmpeg source :/)
mkv seems to work (but it was working before)

https://cloud.mail.ru/public/5AM1/275yC576u

How to test those 'tb/bb/tt/bt' cases? There must be some  artificial picture 
clearly showing if I did it wrong ..Not found it yet.




diff --git a/cinelerra-5.1/cinelerra/ffmpeg.C b/cinelerra-5.1/cinelerra/ffmpeg.C
index 97b6698a..0f41bd23 100644
--- a/cinelerra-5.1/cinelerra/ffmpeg.C
+++ b/cinelerra-5.1/cinelerra/ffmpeg.C
@@ -1213,6 +1213,40 @@ int FFVideoStream::decode_frame(AVFrame *frame)
 	return 1;
 }
 
+int FFVideoStream::probe(int64_t pos)
+{
+	int ret = video_seek(pos);
+	if( ret < 0 ) return -1;
+	if( !frame && !(frame=av_frame_alloc()) ) {
+		fprintf(stderr, "FFVideoStream::probe: av_frame_alloc failed\n");
+		return -1;
+	}
+		
+	if (ffmpeg->interlace_from_codec)
+		return 1;
+
+		ret = read_frame(frame);
+		if( ret > 0 ) {
+			//printf("codec interlace: %i \n",frame->interlaced_frame);
+			//printf("codec tff: %i \n",frame->top_field_first);
+
+			if (!frame->interlaced_frame)
+				ffmpeg->interlace_from_codec = AV_FIELD_PROGRESSIVE;
+			if ((frame->interlaced_frame) && (frame->top_field_first))
+				ffmpeg->interlace_from_codec = AV_FIELD_TT;
+			if ((frame->interlaced_frame) && (!frame->top_field_first))
+				ffmpeg->interlace_from_codec = AV_FIELD_BB;
+			//printf("Interlace mode from codec: %i\n", ffmpeg->interlace_from_codec);
+
+	}
+
+	if( frame->format == AV_PIX_FMT_NONE || frame->width <= 0 || frame->height <= 0 )
+		ret = -1;
+
+	ret = ret > 0 ? 1 : ret < 0 ? -1 : 0;
+	return ret;
+}
+
 int FFVideoStream::load(VFrame *vframe, int64_t pos)
 {
 	int ret = video_seek(pos);
@@ -1221,6 +1255,8 @@ int FFVideoStream::load(VFrame *vframe, int64_t pos)
 		fprintf(stderr, "FFVideoStream::load: av_frame_alloc failed\n");
 		return -1;
 	}
+	
+
 	int i = MAX_RETRY + pos - curr_pos;
 	int64_t cache_start = 0;
 	while( ret>=0 && !flushed && curr_pos<=pos && --i>=0 ) {
@@ -1391,6 +1427,7 @@ int FFVideoStream::encode(VFrame *vframe)
 
 int FFVideoStream::drain()
 {
+
 	return 0;
 }
 
@@ -1776,6 +1813,7 @@ FFMPEG::FFMPEG(FileBase *file_base)
 	flow = 1;
 	decoding = encoding = 0;
 	has_audio = has_video = 0;
+	interlace_from_codec = 0;
 	opts = 0;
 	opt_duration = -1;
 	opt_video_filter = 0;
@@ -2411,6 +2449,10 @@ int FFMPEG::info(char *text, int len)
 		AVPixelFormat pix_fmt = (AVPixelFormat)st->codecpar->format;
 		const char *pfn = av_get_pix_fmt_name(pix_fmt);
 		report(" pix %s\n", pfn ? pfn : unkn);
+		int interlace = st->codecpar->field_order;
+		report("  interlace (container level): %i\n", interlace ? interlace : -1);
+		int interlace_codec = interlace_from_codec;
+		report("  interlace (codec level): %i\n", interlace_codec ? interlace_codec : -1);
 		enum AVColorSpace space = st->codecpar->color_space;
 		const char *nm = av_color_space_name(space);
 		report("    color space:%s", nm ? nm : unkn);
@@ -2889,6 +2931,25 @@ int FFMPEG::open_encoder(const char *type, const char *spec)
 			vid->interlaced = asset->interlace_mode == ILACE_MODE_TOP_FIRST ||
 				asset->interlace_mode == ILACE_MODE_BOTTOM_FIRST ? 1 : 0;
 			vid->top_field_first = asset->interlace_mode == ILACE_MODE_TOP_FIRST ? 1 : 0;
+			switch (asset->interlace_mode)	{		
+			case ILACE_MODE_TOP_FIRST: 
+			if (ctx->codec->id == AV_CODEC_ID_MJPEG)
+			av_dict_set(&sopts, "field_order", "tt", 0); 
+			else
+			av_dict_set(&sopts, "field_order", "tb", 0); 
+			if (ctx->codec_id != AV_CODEC_ID_MJPEG) 
+			av_dict_set(&sopts, "flags", "+ilme+ildct", 0);
+			break;
+			case ILACE_MODE_BOTTOM_FIRST: 
+			if (ctx->codec->id == AV_CODEC_ID_MJPEG)
+			av_dict_set(&sopts, "field_order", "bb", 0); 
+			else
+			av_dict_set(&sopts, "field_order", "bt", 0); 
+			if (ctx->codec_id != AV_CODEC_ID_MJPEG)
+			av_dict_set(&sopts, "flags", "+ilme+ildct", 0);
+			break;
+			case ILACE_MODE_NOTINTERLACED: av_dict_set(&sopts, "field_order", "progressive", 0); break;
+			}
 			break; }
 		default:
 			eprintf(_("not audio/video, %s:%s\n"), codec_name, filename);
@@ -3181,6 +3242,33 @@ int FFMPEG::audio_seek(int stream, int64_t pos)
 	return 0;
 }
 
+int FFMPEG::video_probe(int64_t pos)
+{
+	int vidx = vstrm_index[0].st_idx;
+	FFVideoStream *vid = ffvideo[vidx];
+	vid->probe(pos);
+	
+	int interlace1 = interlace_from_codec;
+	//printf("interlace from codec: %i\n", interlace1);
+
+	switch (interlace1)
+	{
+	case AV_FIELD_TT:
+	case AV_FIELD_TB:
+	    return ILACE_MODE_TOP_FIRST;
+	case AV_FIELD_BB:
+	case AV_FIELD_BT:
+	    return ILACE_MODE_BOTTOM_FIRST;
+	case AV_FIELD_PROGRESSIVE:
+	    return ILACE_MODE_NOTINTERLACED;
+	default:
+	    return ILACE_MODE_UNDETECTED;
+	}
+
+}
+
+
+
 int FFMPEG::video_seek(int stream, int64_t pos)
 {
 	int vidx = vstrm_index[stream].st_idx;
@@ -3468,7 +3556,22 @@ int FFMPEG::ff_coded_height(int stream)
 
 float FFMPEG::ff_aspect_ratio(int stream)
 {
-	return ffvideo[stream]->aspect_ratio;
+	//return ffvideo[stream]->aspect_ratio;
+	AVFormatContext *fmt_ctx = ffvideo[stream]->fmt_ctx;
+	AVStream *strm = ffvideo[stream]->st;
+	AVCodecParameters *par = ffvideo[stream]->st->codecpar;
+	AVRational dar;
+	AVRational sar = av_guess_sample_aspect_ratio(fmt_ctx, strm, NULL);
+        if (sar.num) {
+            printf("sample_aspect_ratio, %f \n", av_q2d(sar));
+            av_reduce(&dar.num, &dar.den,
+                      par->width  * sar.num,
+                      par->height * sar.den,
+                      1024*1024);
+                      printf("display_aspect_ratio, %f \n", av_q2d(dar));
+                      return av_q2d(dar);
+                      }
+        return ffvideo[stream]->aspect_ratio;
 }
 
 const char* FFMPEG::ff_video_codec(int stream)
@@ -3509,6 +3612,31 @@ int FFMPEG::ff_video_mpeg_color_range(int stream)
 	return ffvideo[stream]->st->codecpar->color_range == AVCOL_RANGE_MPEG ? 1 : 0;
 }
 
+int FFMPEG::ff_interlace(int stream)
+{
+// https://ffmpeg.org/doxygen/trunk/structAVCodecParserContext.html
+/* reads from demuxer because codec frame not ready */
+	int interlace0 = ffvideo[stream]->st->codecpar->field_order;
+	printf("interlace from demux: %i\n", interlace0);
+
+	switch (interlace0)
+	{
+	case AV_FIELD_TT:
+	case AV_FIELD_TB:
+	    return ILACE_MODE_TOP_FIRST;
+	case AV_FIELD_BB:
+	case AV_FIELD_BT:
+	    return ILACE_MODE_BOTTOM_FIRST;
+	case AV_FIELD_PROGRESSIVE:
+	    return ILACE_MODE_NOTINTERLACED;
+	default:
+	    return ILACE_MODE_UNDETECTED;
+	}
+	
+}
+
+
+
 int FFMPEG::ff_cpus()
 {
 	return !file_base ? 1 : file_base->file->cpus;
diff --git a/cinelerra-5.1/cinelerra/ffmpeg.h b/cinelerra-5.1/cinelerra/ffmpeg.h
index 2e1f201f..4f1624ce 100644
--- a/cinelerra-5.1/cinelerra/ffmpeg.h
+++ b/cinelerra-5.1/cinelerra/ffmpeg.h
@@ -256,6 +256,7 @@ public:
 
 	int init_frame(AVFrame *picture);
 	int load(VFrame *vframe, int64_t pos);
+	int probe(int64_t pos);
 	int video_seek(int64_t pos);
 	int encode(VFrame *vframe);
 	int drain();
@@ -383,6 +384,7 @@ public:
 	double get_initial_timecode(int data_type, int channel, double frame_rate);
 
 	int audio_seek(int ch, int64_t pos);
+	int video_probe(int64_t pos);
 	int video_seek(int layer, int64_t pos);
 
 	int decode(int chn, int64_t pos, double *samples, int len);
@@ -434,6 +436,7 @@ public:
 
 	int decoding, encoding;
 	int has_audio, has_video;
+	int interlace_from_codec;
 
 	FFMPEG(FileBase *file_base=0);
 	~FFMPEG();
@@ -463,6 +466,7 @@ public:
 	float ff_aspect_ratio(int stream);
 	int ff_color_range(int stream);
 	int ff_color_space(int stream);
+	int ff_interlace(int stream);
 	double ff_frame_rate(int stream);
 	const char *ff_video_codec(int stream);
 	int64_t ff_video_frames(int stream);
diff --git a/cinelerra-5.1/cinelerra/fileffmpeg.C b/cinelerra-5.1/cinelerra/fileffmpeg.C
index ff206b10..eed14f20 100644
--- a/cinelerra-5.1/cinelerra/fileffmpeg.C
+++ b/cinelerra-5.1/cinelerra/fileffmpeg.C
@@ -326,7 +326,7 @@ int FileFFMPEG::open_file(int rd, int wr)
 	int result = 0;
 	if( ff ) return 1;
 	ff = new FFMPEG(this);
-
+	
 	if( rd ) {
 		result = ff->init_decoder(asset->path);
 		if( !result ) result = ff->open_decoder();
@@ -342,6 +342,11 @@ int FileFFMPEG::open_file(int rd, int wr)
 			int video_layers = ff->ff_total_video_layers();
 			if( video_layers > 0 ) {
 				asset->video_data = 1;
+				asset->aspect_ratio = ff->ff_aspect_ratio(0);
+				printf("ff_aspect_ratio, %f \n", asset->aspect_ratio);
+				if (!asset->interlace_mode) asset->interlace_mode = ff->ff_interlace(0);
+				ff->video_probe(1);
+				 if (!asset->interlace_mode && (ff->interlace_from_codec) ) asset->interlace_mode = ff->video_probe(1); 
 				if( !asset->layers ) asset->layers = video_layers;
 				asset->actual_width = ff->ff_video_width(0);
 				asset->actual_height = ff->ff_video_height(0);
@@ -1938,6 +1943,15 @@ int FFOptionsFormatView::handle_event()
 {
 	Asset *asset = fmt_config->asset;
 	char *format_name = asset->fformat;
+	char *replace_name0 = "mov";
+	char *replace_name1 = "mpegts";
+	char *replace_name2 = "matroska";
+	if (!strcmp(format_name, "qt"))
+		format_name = replace_name0; // fixup
+	if (!strcmp(format_name, "m2ts"))
+		format_name = replace_name1; // fixup
+	if (!strcmp(format_name, "mkv"))
+		format_name = replace_name2; // fixup
 	avformat_free_context(fmt_ctx);  fmt_ctx = 0;
 	int ret = avformat_alloc_output_context2(&fmt_ctx, 0, format_name, 0);
 	if( ret || !fmt_ctx ) {
diff --git a/cinelerra-5.1/cinelerra/mwindow.C b/cinelerra-5.1/cinelerra/mwindow.C
index f245018a..6621d11a 100644
--- a/cinelerra-5.1/cinelerra/mwindow.C
+++ b/cinelerra-5.1/cinelerra/mwindow.C
@@ -4493,11 +4493,14 @@ static inline int gcd(int m, int n)
 int MWindow::create_aspect_ratio(float &w, float &h, int width, int height)
 {
 	w = 1;  h = 1;
+	double ar;
+	
 	if(!width || !height) return 1;
 	if( width == 720 && (height == 480 || height == 576) ) {
 		w = 4;  h = 3;  return 0; // for NTSC and PAL
 	}
-	double ar = (double)width / height;
+	
+	ar = (double)width / height;
 // square-ish pixels
 	if( EQUIV(ar, 1.0000) ) return 0;
 	if( EQUIV(ar, 1.3333) ) { w = 4;  h = 3;  return 0; }
@@ -4505,6 +4508,8 @@ int MWindow::create_aspect_ratio(float &w, float &h, int width, int height)
 	if( EQUIV(ar, 2.1111) ) { w = 19; h = 9;  return 0; }
 	if( EQUIV(ar, 2.2222) ) { w = 20; h = 9;  return 0; }
 	if( EQUIV(ar, 2.3333) ) { w = 21; h = 9;  return 0; }
+	if( EQUIV(ar, 2.37037) ) { w = 64; h = 27;  return 0; }
+
 	int ww = width, hh = height;
 	// numerator, denominator must be under mx
 	int mx = 255, n = gcd(ww, hh);
@@ -5048,12 +5053,26 @@ int MWindow::select_asset(Asset *asset, int vstream, int astream, int delete_tra
 		session->output_w = width;
 		session->output_h = height;
 		session->frame_rate = framerate;
+		session->interlace_mode = asset->interlace_mode;
 		// not, asset->actual_width/actual_height
 		asset->width = session->output_w;
 		asset->height = session->output_h;
 		asset->frame_rate = session->frame_rate;
+		
 		create_aspect_ratio(session->aspect_w, session->aspect_h,
 			session->output_w, session->output_h);
+	float ar = asset->aspect_ratio;
+	if (ar) {
+	//printf ("Aspect ratio from asset: %f \n", ar);
+	if( EQUIV(ar, 1.3333) ) { session->aspect_w = 4;  session->aspect_h = 3;  }
+	if( EQUIV(ar, 1.7777) ) { session->aspect_w = 16; session->aspect_h = 9;   }
+	if( EQUIV(ar, 2.1111) ) { session->aspect_w = 19; session->aspect_h = 9;  }
+	if( EQUIV(ar, 2.2222) ) { session->aspect_w = 20; session->aspect_h = 9;   }
+	if( EQUIV(ar, 2.3333) ) { session->aspect_w = 21; session->aspect_h = 9;   }
+	if( EQUIV(ar, 2.370370) ) { session->aspect_w = 64; session->aspect_h = 27; }
+	}
+			
+			
 		Track *track = edl->tracks->first;
 		for( Track *next_track=0; track; track=next_track ) {
 			next_track = track->next;
-- 
Cin mailing list
[email protected]
https://lists.cinelerra-gg.org/mailman/listinfo/cin

Reply via email to