2012-07-18 45 views
3

編輯:在以前的版本中,我使用了一個非常老的ffmpeg API。我現在使用最新的庫。問題只是輕微改變,從「主」到「高」。ffmpeg API h264編碼視頻無法在所有平臺上播放

我使用ffmpeg C API在C++中創建mp4視頻。

我希望生成的視頻具有「約束基線」配置文件,以便可以在儘可能多的平臺上播放結果視頻,尤其是移動視頻,但每次我都會獲得「高」配置文件,即使我將編解碼器配置文件硬編碼爲FF_PROFILE_H264_CONSTRAINED_BASELINE。因此,視頻無法在我們所有的測試平臺上播放。

這就是「ffprobe video.mp4 -show_streams」講述我的視頻流:

Metadata: 
major_brand  : isom 
minor_version : 512 
compatible_brands: isomiso2avc1mp41 
creation_time : 1970-01-01 00:00:00 
encoder   : Lavf53.5.0 
    Duration: 00:00:13.20, start: 0.000000, bitrate: 553 kb/s 
Stream #0:0(und): Video: h264 (Main) (avc1/0x31637661), yuv420p, 320x180, 
424 kb/s, 15 fps, 15 tbr, 15 tbn, 30 tbc 
Metadata: 
    creation_time : 1970-01-01 00:00:00 
    handler_name : VideoHandler 
Stream #0:1(und): Audio: aac (mp4a/0x6134706D), 44100 Hz, stereo, s16, 12 
kb/s 
Metadata: 
    creation_time : 1970-01-01 00:00:00 
    handler_name : SoundHandler 
-------VIDEO STREAM-------- 
[STREAM] 
index=0 
codec_name=h264 
codec_long_name=H.264/AVC/MPEG-4 AVC/MPEG-4 part 10 

profile=High <-- This should be "Constrained Baseline" 

codec_type=video 
codec_time_base=1/30 
codec_tag_string=avc1 
codec_tag=0x31637661 
width=320 
height=180 
has_b_frames=0 
sample_aspect_ratio=N/A 
display_aspect_ratio=N/A 
pix_fmt=yuv420p 
level=30 
timecode=N/A 
is_avc=1 
nal_length_size=4 
id=N/A 
r_frame_rate=15/1 
avg_frame_rate=15/1 
time_base=1/15 
start_time=0.000000 
duration=13.200000 
bit_rate=424252 
nb_frames=198 
nb_read_frames=N/A 
nb_read_packets=N/A 
TAG:creation_time=1970-01-01 00:00:00 
TAG:language=und 
TAG:handler_name=VideoHandler 
[/STREAM] 
-------AUDIO STREAM-------- 
[STREAM] 
index=1 
codec_name=aac 
codec_long_name=Advanced Audio Coding 
profile=unknown 
codec_type=audio 
codec_time_base=1/44100 
codec_tag_string=mp4a 
codec_tag=0x6134706d 
sample_fmt=s16 
sample_rate=44100 
channels=2 
bits_per_sample=0 
id=N/A 
r_frame_rate=0/0 
avg_frame_rate=0/0 
time_base=1/44100 
start_time=0.000000 
duration=13.165714 
bit_rate=125301 
nb_frames=567 
nb_read_frames=N/A 
nb_read_packets=N/A 
TAG:creation_time=1970-01-01 00:00:00 
TAG:language=und 
TAG:handler_name=SoundHandler 
[/STREAM] 

這是我使用添加一個視頻流的功能。所有這一切都來自ptr-值>從外部定義,做那些值必須在特定的值,以獲得正確的配置文件?:

static AVStream *add_video_stream(Cffmpeg_dll * ptr, AVFormatContext *oc, enum CodecID codec_id) 
{ 
AVCodecContext *c; 
AVStream *st; 
AVCodec* codec; 

// Get correct codec 
codec = avcodec_find_encoder(codec_id); 
if (!codec) { 
    av_log(NULL, AV_LOG_ERROR, "%s","Video codec not found\n"); 
    exit(1); 
} 

// Create stream 
st = avformat_new_stream(oc, codec); 
if (!st) { 
    av_log(NULL, AV_LOG_ERROR, "%s","Could not alloc stream\n"); 
    exit(1); 
} 

c = st->codec; 

/* Get default values */ 
codec = avcodec_find_encoder(codec_id); 
if (!codec) { 
    av_log(NULL, AV_LOG_ERROR, "%s","Video codec not found (default values)\n"); 
    exit(1); 
} 
avcodec_get_context_defaults3(c, codec); 

c->codec_id = codec_id; 
c->codec_type = AVMEDIA_TYPE_VIDEO; 

c->bit_rate = ptr->video_bit_rate; 
av_log(NULL, AV_LOG_ERROR, " Bit rate: %i", c->bit_rate); 

    c->qmin = ptr->qmin; 
    c->qmax = ptr->qmax; 
    c->me_method = ptr->me_method; 
    c->me_subpel_quality = ptr->me_subpel_quality; 
    c->i_quant_factor = ptr->i_quant_factor; 
    c->qcompress = ptr->qcompress; 
    c->max_qdiff = ptr->max_qdiff; 

    // We need to set the level and profile to get videos that play (hopefully) on all platforms 
    c->level = 30; 
    c->profile = FF_PROFILE_H264_CONSTRAINED_BASELINE; 

c->width = ptr->dstWidth; 
c->height = ptr->dstHeight; 

c->time_base.den = ptr->fps; 
c->time_base.num = 1; 
c->gop_size = ptr->fps; 
c->pix_fmt = STREAM_PIX_FMT; 
c->max_b_frames = 0; 

// some formats want stream headers to be separate 
if(oc->oformat->flags & AVFMT_GLOBALHEADER) 
    c->flags |= CODEC_FLAG_GLOBAL_HEADER; 

return st; 
} 

附加信息:

當參考視頻,我使用Mozilla作爲可在每個平臺/瀏覽器上播放的示例的gizmo.mp4。它絕對具有「約束基線」配置文件,並且絕對適用於我們所有測試的智能手機。 You can download it here.我們自制的視頻不適用於所有平臺,我相信這是因爲配置文件。

我也在使用qt-faststart.exe在創建mp4後將標題移動到文件的開頭,因爲這不能在C++中直接完成。這可能是問題嗎?

顯然,我在做東西錯了,但我不知道它可能是什麼。我會感謝每一個提示;)

+0

你應該在ffmpeg郵件列表上提交一個錯誤報告。如您所期望的,這應該表示爲基線或基線限制。 – SilverbackNet 2012-07-18 09:19:49

+0

我更新了我的ffmpeg版本,問題從「Main」稍微變爲「High」配置文件。 @SilverbackNet如果這不能解決,將會做。 – TheSHEEEP 2012-07-18 12:00:10

+0

有趣的是,當您通過命令行使用ffmpeg.exe並設置「-vprofile baseline」時,它按預期工作。我們對ffmpeg.exe和我們使用的C庫都使用相同的ffmpeg版本。 – TheSHEEEP 2012-07-18 12:04:56

回答

7

我有解決方案。在ffmpeg bug跟蹤器中花費一些時間和討論並瀏覽配置文件設置示例後,我終於找到了解決方案。

一個需要使用av_opt_set(codecContext-> priv_data, 「輪廓」, 「基線」(或任何其他所需的個人資料),AV_OPT_SEARCH_CHILDREN)

所以在我的情況下,這將是:

錯誤:

// We need to set the level and profile to get videos that play (hopefully) on all platforms 
c->level = 30; 
c->profile = FF_PROFILE_H264_CONSTRAINED_BASELINE; 

正確:

// Set profile to baseline 
av_opt_set(c->priv_data, "profile", "baseline", AV_OPT_SEARCH_CHILDREN); 

完全不直觀,違背了API的其他用法,但這是ffmpeg的哲學。你不需要了解它,你只需要瞭解如何使用它;)

+0

爲什麼選擇配置文件基準?您的意思是配置文件constrainted_baseline的視頻無法在某些設備上正常播放? – dragonfly 2015-09-23 10:51:44

+0

「基準」實際上最終在結果文件中被限定爲基線。 – TheSHEEEP 2015-09-23 11:22:44

+0

據我所知,baseline和constrained_baseline是h264的2個不同配置文件。你有什麼意見? – dragonfly 2015-09-23 11:48:35