Welcome to Doom9's Forum, THE in-place to be for everyone interested in DVD conversion.

Before you start posting please read the forum rules. By posting to this forum you agree to abide by the rules.

 

Go Back   Doom9's Forum > Video Encoding > MPEG-4 AVC / H.264

Reply
 
Thread Tools Search this Thread Display Modes
Old 16th April 2014, 21:15   #1  |  Link
njahnke
Registered User
 
njahnke's Avatar
 
Join Date: Oct 2004
Location: lubbock, tx, usa
Posts: 33
what is the difference between these two h.264 mp4s?

hi all.

i wrote a qt c++ program that uses the ffmpeg api to transcode video to h.264 mp4. i know, i know - don't use the ffmpeg api to control x264. but it was working fine until i upgraded ffmpeg and x264 to the latest versions.

last release build used ffmpeg from git from around last summer (N-54452-g621ab4e). x264 was "core 135 r2 f0c1c53".

i updated ffmpeg to 2.2.1 and x264 to "core 142 r2 956c8d8".

i encoded the same test video before and after updating the libraries. you can find them here:

http://nate.quandra.org/kowz_good.mp4
http://nate.quandra.org/kowz_bad.mp4

both play fine in good players, but in the bad player (quicktime pre 7.7) i get this:



so updating ffmpeg and/or x264 broke playback in old quicktime. it's pretty bizarre because the same settings are being passed to x264. also x264 commandline and ffmpeg commandline do not create video with the problem.

i have already tried mediainfo and ffprobe -show_streams and i cannot find any difference between the files. it's a mystery to me. to be honest, i don't even care about old quicktime, but like they say: "where there's smoke ..."

if anyone loves a mystery, please help me out.

my ffmpeg code:
Code:
filename_string = temp_out_file.fileName()+"v.mp4";
QByteArray filename_ba = filename_string.toLocal8Bit();
char *filename_pointer = filename_ba.data();
avformat_alloc_output_context2(&oc, NULL, NULL, filename_pointer);
Q_ASSERT(oc);


codec = avcodec_find_encoder(AV_CODEC_ID_H264);
if (!codec) {
	fprintf(stderr, "Codec not found\n");
	exit(1);
}


//add to output stream context
st = avformat_new_stream(oc, codec);
if (!st) {
	fprintf(stderr, "Could not allocate stream\n");
	exit(1);
}
st->id = oc->nb_streams-1;
//c = avcodec_alloc_context3(codec);
c = st->codec;
if (!c) {
	fprintf(stderr, "Could not allocate video codec context\n");
	exit(1);
}

/* Some formats want stream headers to be separate. */
if (oc->oformat->flags & AVFMT_GLOBALHEADER) {
	c->flags |= CODEC_FLAG_GLOBAL_HEADER;
}


AVDictionary *opts = NULL;

av_dict_set(&opts, "preset", "veryslow", 0);

//http://mewiki.project357.com/wiki/X264_Encoding_Suggestions#QuickTime_Player_X_compatibility
//this doesn't work because we set the profile and/or level for every quality below (20130330)
av_dict_set(&opts, "refs", "4", 0);
av_dict_set(&opts, "qpmin", "4", 0);


av_dict_set(&opts, "profile", "high", 0);
av_dict_set(&opts, "level", "4.1", 0); //bluray compatibility level


c->pix_fmt = (AVPixelFormat)video_information.colorspace;

QString stat_file_name = temp_out_file.fileName()+".stats";
stat_file_name_ba = stat_file_name.toLocal8Bit();
char *stat_file_name_pointer = stat_file_name_ba.data();

av_dict_set(&opts, "stats", stat_file_name_pointer, 0);

if (pass == 1) {
	av_dict_set(&opts, "crf", "17", 0);
	av_dict_set(&opts, "fastfirstpass", "0", 0);
	c->flags |= CODEC_FLAG_PASS1;
} else if (pass == 2) {
	c->bit_rate = video_information.bitrate_kbit * 1000;
	c->flags |= CODEC_FLAG_PASS2;
}

c->thread_count = 0;

c->width = video_information.width_after_cropping;
c->height = video_information.height_after_cropping;

c->sample_aspect_ratio.num = st->sample_aspect_ratio.num = aspect_ratio_num * video_information.height;
c->sample_aspect_ratio.den = st->sample_aspect_ratio.den = aspect_ratio_den * video_information.width;

c->time_base.num = timebase_num;
c->time_base.den = timebase_den;

if (mutex) mutex->lock();
int ret = avcodec_open2(c, codec, &opts);
if (mutex) mutex->unlock();
if (ret < 0) {
	qDebug() <<  "Could not open video codec";
	exit(1);
}


/* open the output file, if needed */
if (avio_open(&oc->pb, filename_pointer, AVIO_FLAG_WRITE) < 0) {
	fprintf(stderr, "Error occurred when opening video output file\n");
	return;
}

/* Write the stream header, if any. */
if (avformat_write_header(oc, NULL) < 0) {
	fprintf(stderr, "Error occurred when writing video header\n");
	return;
}
njahnke is offline   Reply With Quote
Old 16th April 2014, 23:42   #2  |  Link
poisondeathray
Registered User
 
Join Date: Sep 2007
Posts: 5,017
possibly a bad mux;

demuxing, then remuxing with lsmash or mp4box seems to fix playback in old QT v7 (at least on Windows)
poisondeathray is offline   Reply With Quote
Old 17th April 2014, 00:14   #3  |  Link
njahnke
Registered User
 
njahnke's Avatar
 
Join Date: Oct 2004
Location: lubbock, tx, usa
Posts: 33
ok, that is kind of what i suspected ... is there something wrong with how i am writing to the mp4 output? see my code below. in particular, using the ffmpeg commandline program built with the new libraries doesn't exhibit this problem ... so i doubt it is a problem with ffmpeg. rather how i am using the library is incorrect.

Code:
//after avcodec_encode_video2()
if (c->coded_frame->key_frame) pkt.flags |= AV_PKT_FLAG_KEY;
pkt.stream_index = st->index;
av_interleaved_write_frame(oc, &pkt);



//when it's time to finish the file
av_write_trailer(oc);

if (mutex) mutex->lock();
avcodec_close(st->codec);
if (mutex) mutex->unlock();

/* Free the streams. */
for (uint i = 0; i < oc->nb_streams; i++) {
	av_freep(&oc->streams[i]->codec);
	av_freep(&oc->streams[i]);
}

avio_close(oc->pb);

/* free the stream */
av_free(oc);
njahnke is offline   Reply With Quote
Old 16th May 2014, 16:30   #4  |  Link
njahnke
Registered User
 
njahnke's Avatar
 
Join Date: Oct 2004
Location: lubbock, tx, usa
Posts: 33
for reference, this was the problem (after calling avcodec_encode_video2()):

Code:
if (c->coded_frame->key_frame) {
        pkt.flags |= AV_PKT_FLAG_KEY;
}
these lines are apparently no longer necessary and actually harmful to the mux as of ffmpeg with x264 from this year or so. apparently the AVPacket key frame flag is now set correctly by the encoder and it is harmful to set it manually in this way. i figured it out by a side-by-side comparison with the muxing.c example in the ffmpeg distribution.
njahnke is offline   Reply With Quote
Reply

Tags
ffmpeg x264 mp4 quicktime

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +1. The time now is 02:31.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2022, vBulletin Solutions Inc.