4

ビデオをフレームごとにトランスコードし、x264+ffmpegを使用してエンコードしています。元のビデオは正常に再生されますが、トランスコードされたビデオの最初の数フレームは灰色のアーティファクトを示しています。これは時間の圧縮によるものであり、これらのアーティファクトは数フレーム後に消えることを理解しています。

最初と2番目のフレームであるこれらの2つの写真を参照してください。3番目のフレームは正常です(つまり、灰色のアーティファクトがなく、2番目のフレームのようにぼやけていません) 最初のフレーム 2番目のフレーム

これらのアーティファクトが表示されないように、最初のフレームをキーフレームにする(つまり、出力ビデオで完全にエンコードする)にはどうすればよいですか?

編集-詳細

これが私がもっと詳しくやっていることです。ビットフォームの違いのチュートリアルを使用して、フレームごとにビデオを読み取り、各フレームを新しいビデオに再エンコードしました。私のエンコーディングパラメータは次のとおりです。

avcodec_get_context_defaults3(c, *codec);
c->codec_id = codec_id;
c->bit_rate = output_bitrate;
/* Resolution must be a multiple of two. */
c->width    = output_width;
c->height   = output_height;
/* timebase: This is the fundamental unit of time (in seconds) in terms
 * of which frame timestamps are represented. For fixed-fps content,
 * timebase should be 1/framerate and timestamp increments should be
 * identical to 1. */
st->r_frame_rate.num = output_framerate_num;
st->r_frame_rate.den = output_framerate_den;
c->time_base.den = output_timebase_den;
c->time_base.num = output_timebase_num;
c->gop_size      = 3; /* emit one intra frame every twelve frames at most */
c->pix_fmt       = STREAM_PIX_FMT;
if (c->codec_id == AV_CODEC_ID_MPEG2VIDEO) {
    /* just for testing, we also add B frames */
    c->max_b_frames = 2;
}
if (c->codec_id == AV_CODEC_ID_MPEG1VIDEO) {
    /* Needed to avoid using macroblocks in which some coeffs overflow.
     * This does not happen with normal video, it just happens here as
     * the motion of the chroma plane does not match the luma plane. */
    c->mb_decision = 2;
}
c->max_b_frames = 2;
c->scenechange_threshold = 0;
c->rc_buffer_size = 0;
c->me_method = ME_ZERO;

次に、各フレームを処理します。おそらくそこで何か間違ったことをします。デコードビット:

while(av_read_frame(gFormatCtx, &packet)>=0) {
    // Is this a packet from the video stream?
    if(packet.stream_index==gVideoStreamIndex) {
        // Decode video frame
        avcodec_decode_video2(gVideoCodecCtx, pCurrentFrame, &frameFinished, &packet);
        // Did we get a video frame?
        if(frameFinished) {
            [...]
            if(firstPts == -999) /*Initial value*/
                firstPts = packet.pts;
            deltaPts = packet.pts - firstPts;
            double seconds = deltaPts*av_q2d(gFormatCtx->streams[gVideoStreamIndex]->time_base);
            [...]
            muxing_writeVideoFrame(pCurrentFrame, packet.pts);
        }
    }
}

実際の執筆:

int muxing_writeVideoFrame(AVFrame *frame, int64_t pts)
{
frameCount = frameCount +1;
if(frameCount > 0)
{
    if (video_st)
        video_pts = (double)video_st->pts.val * video_st->time_base.num /
                    video_st->time_base.den;
    else
        video_pts = 0.0;

    if (video_st && !(video_st && audio_st && audio_pts < video_pts))
    {
        frame->pts = pts;//av_rescale_q(frame_count, video_st->codec->time_base, video_st->time_base);
        write_video_frame(oc, video_st, frame);
    }
}

return 0;
}

static int write_video_frame(AVFormatContext *oc, AVStream *st, AVFrame *frame)
{
    int ret;
    static struct SwsContext *sws_ctx;
    //LOGI(10, frame_count);
    AVCodecContext *c = st->codec;

    /* encode the image */
    AVPacket pkt;
    int got_output;
    av_init_packet(&pkt);
    pkt.data = NULL;    // packet data will be allocated by the encoder
    pkt.size = 0;
ret = avcodec_encode_video2(c, &pkt, frame, &got_output);
if (ret < 0) {
    fprintf(stderr, "Error encoding video frame: %s\n", av_err2str(ret));
    exit(1);
}
/* If size is zero, it means the image was buffered. */
if (got_output) {
    if (c->coded_frame->key_frame)
        pkt.flags |= AV_PKT_FLAG_KEY;
    pkt.stream_index = st->index;
    /* Write the compressed frame to the media file. */
    ret = av_interleaved_write_frame(oc, &pkt);
} else {
    ret = 0;
}

    if (ret != 0) {
        LOGI(10, av_err2str(ret));
        exit(1);
    }
    frame_count++;
    return got_output;
}
4

2 に答える 2

1

これは、動画がキーフレームで始まっていないため です。これを修正するには、AviDemuxを使用します。バージョン 2.6 以降

  • MP4マルチプレクサ
  • MP4v2 マルチプレクサ

キーフレームなしで開始するビデオをサポートする可能性があります。

于 2013-02-03T20:32:34.243 に答える
1

あなたの問題は、エンコードではなくデコード部分にある可能性が最も高いです(x264はそのようなアーティファクトを生成できません)。そして、上で述べたように、キーフレームからではなくデコードを開始しているように見えます (または、ストリームがオープンゴップで、最初の B フレームを破棄しなかった可能性があります)。

于 2013-02-03T22:04:37.363 に答える