3

編集:以前のバージョンでは、非常に古い ffmpeg API を使用していました。現在、最新のライブラリを使用しています。問題は、「メイン」から「高」にわずかに変化しただけです。

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 を使用します。それは間違いなく「制約付きベースライン」プロファイルを持ち、テスト中のすべてのスマートフォンで確実に動作します. こちらからダウンロードできます。私たちの自作ビデオは、すべてのプラットフォームで機能するとは限りません。これは、プロファイルが原因であると確信しています。

また、mp4 を作成した後、 qt-faststart.exeを使用してヘッダーをファイルの先頭に移動しています。これは、C++ では適切な方法で直接行うことができないためです。それが問題でしょうか?

明らかに、私は何か間違ったことをしていますが、それが何であるかはわかりません。私はすべてのヒントに感謝します;)

4

1 に答える 1

7

私は解決策を持っています。ffmpegバグトラッカーで時間をかけて議論し、プロファイル設定の例を閲覧した後、最終的に解決策を見つけました.

av_opt_set(codecContext->priv_data, "profile", "baseline" (またはその他の必要なプロファイル), 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 の哲学です。理解する必要はありません。使い方を理解するだけで十分です ;)

于 2012-07-19T09:46:28.273 に答える