ffmpegソースコードプロファイル(六)符号化-av_write_frame(),av_write_trailer()

7669 ワード

1.av_write_frame()


av_write_frame()は、libavformatavformatにあると宣言するフレームオーディオデータを出力するために使用される.h,以下に示す.
int av_write_frame(AVFormatContext *s, AVPacket *pkt); 
 :

    s: AVFormatContext。
    pkt: AVPacket。

 0。

av_write_frame()の定義はlibavformatmuxにある.c,以下に示す.
    int av_write_frame(AVFormatContext *s, AVPacket *pkt)  
    {  
        int ret;  

        ret = check_packet(s, pkt);  
        if (ret < 0)  
            return ret;  
        //Packet NULLFlush Encoder  
        if (!pkt) {  
            if (s->oformat->flags & AVFMT_ALLOW_FLUSH) {  
                ret = s->oformat->write_packet(s, NULL);  
                if (s->flush_packets && s->pb && s->pb->error >= 0 && s->flags & AVFMT_FLAG_FLUSH_PACKETS)  
                    avio_flush(s->pb);  
                if (ret >= 0 && s->pb && s->pb->error < 0)  
                    ret = s->pb->error;  
                return ret;  
            }  
            return 1;  
        }  

        ret = compute_pkt_fields2(s, s->streams[pkt->stream_index], pkt);  

        if (ret < 0 && !(s->oformat->flags & AVFMT_NOTIMESTAMPS))  
            return ret;  
        //   
        ret = write_packet(s, pkt);  
        if (ret >= 0 && s->pb && s->pb->error < 0)  
            ret = s->pb->error;  

        if (ret >= 0)  
            s->streams[pkt->stream_index]->nb_frames++;  
        return ret;  
    }  

ソースコードからav_write_frame()は主に以下のステップを完了しました:(1)check_を呼び出すpacket()簡単な検出(2)呼び出しcompute_pkt_Fields 2()AVPacketのいくつかの属性値を設定(3)write_を呼び出すpacket()書き込みデータ
これらの関数機能をそれぞれ見てみましょう.check_packet() check_packet()定義はlibavformatmuxにあります.c,以下に示す.
    static int check_packet(AVFormatContext *s, AVPacket *pkt)  
    {  
        if (!pkt)  
            return 0;  

        if (pkt->stream_index < 0 || pkt->stream_index >= s->nb_streams) {  
            av_log(s, AV_LOG_ERROR, "Invalid packet stream index: %d
"
, pkt->stream_index); return AVERROR(EINVAL); } if (s->streams[pkt->stream_index]->codec->codec_type == AVMEDIA_TYPE_ATTACHMENT) { av_log(s, AV_LOG_ERROR, "Received a packet for an attachment stream.
"
); return AVERROR(EINVAL); } return 0; }

コードから分かるようにcheck_packet()の機能は簡単です.まず、入力したAVPacketが空であるかどうかをチェックし、空であれば直接戻ります.そしてAVPacketのstream_をチェックindex(このAVPacketが属するAVStreamがマークされている)の設定が正常かどうかは、負またはAVStreamより大きい個数であればエラーメッセージを返します.
compute_pkt_fields2() compute_pkt_Fields 2()には主に2つの機能がある:一方、AVPacketのduration、dtsなどの情報を計算するために使用される.一方、pts、dtsのこれらのパラメータの妥当性(例えば、PTSがDTSよりも大きいかどうか)を調べるために使用される.
AVOutputFormat->write_packet() write_Packet()関数の最も重要な点は、AVOutputFormatにデータを書き込む方法を呼び出すことです.AVPacketのflagタグにAV_が含まれている場合PKT_FLAG_UNCODED_FRAMEは、AVOutputFormatのwrite_を呼び出しますuncoded_frame()関数;そのタグが含まれていなければwrite_が呼び出されますpacket()関数.write_packet()は実際には関数ポインタであり,特定のAVOutputFormatにおける実装関数を指す.

2.av_write_trailer()


av_write_trailer()はファイルの末尾を出力するために使用され、その宣言はlibavformatavformatにある.h,以下に示す.
int av_write_trailer(AVFormatContext *s);  

出力用のAVFormatContextというパラメータを指定するだけです.関数が正常に実行されると、戻り値は0になります.av_write_trailer()の定義はlibavformatmuxにあります.c,以下に示す.
    int av_write_trailer(AVFormatContext *s)  
    {  
        int ret, i;  

        for (;; ) {  
            AVPacket pkt;  
            ret = interleave_packet(s, &pkt, NULL, 1);  
            if (ret < 0)  
                goto fail;  
            if (!ret)  
                break;  
            // AVPacket  
            ret = write_packet(s, &pkt);  
            if (ret >= 0)  
                s->streams[pkt.stream_index]->nb_frames++;  

            av_free_packet(&pkt);  

            if (ret < 0)  
                goto fail;  
            if(s->pb && s->pb->error)  
                goto fail;  
        }  

    fail:  
        //   
        if (s->oformat->write_trailer)  
            if (ret >= 0) {  
            ret = s->oformat->write_trailer(s);  
            } else {  
                s->oformat->write_trailer(s);  
            }  

        if (s->pb)  
           avio_flush(s->pb);  
        if (ret == 0)  
           ret = s->pb ? s->pb->error : 0;  
        for (i = 0; i < s->nb_streams; i++) {  
            av_freep(&s->streams[i]->priv_data);  
            av_freep(&s->streams[i]->index_entries);  
        }  
        if (s->oformat->priv_class)  
            av_opt_free(s->priv_data);  
        av_freep(&s->priv_data);  
        return ret;  
    }  

ソースコードからav_がわかりますwrite_trailer()は主に以下の2つのステップを完了しました.
(1)ループコールinterleave_packet()およびwrite_Packet()は、まだ出力されていないAVPacketを出力します.
(2)AVOutputFormatを呼び出すwrite_trailer()は、ファイルの末尾を出力します.
AVOutputFormat->write_trailer()AVOutputFormatのwrite_trailer()は、特定のAVOutputFormatの実装関数を指す関数ポインタです.