5

.movファイルからH.26​​4フレームを解析しようとしています。私は、AVFormatのmov.c(FFMPEGの一部)が進むべき道であるという結論に達したと思います。ただし、mov.cは、コメントされていないコードの横にある約2600行です。私はFFMPEGの使用例を探しています。特に、あらゆるファイルタイプの構造を解析しています。構造が非常に似ているため、MPEG4でもQuicktimeムービーでも構いません。

既存の例がない場合(私は何も見つかりません)、誰かがそれを使用して数行のコードを教えてくれたり、開始方法を説明したりできますか?

私がやろうとしていること:AVCaptureSessionを使用してビデオカメラからサンプルをキャプチャし、これらのサンプルをH264でエンコードし、AVAssetsWriter、AVAssetsWriterInput、AVAssetsWriterInputPixelBufferAdaptorを使用してファイルに書き込みます。その理由は、アップルがこれを許可しないため、ハードウェアH264エンコーディングに直接アクセスできないためです。私が今やらなければならないこと(私はよくわからないと思います)は解析されます:

.movファイルの「 mdat」 -atom(ムービーデータ、複数あると思います)。次に「vide」-atom、次にvide-atom内(ビデオデータサンプル、複数ある場合があります)。私が信じているのはフレームであるいくつかの原子があると思います。これらは「avc1」タイプになります(これはH264のタイプです)。私はまだこれをすべて正しく取得していないと確信しているので、これで私を修正してください

私の質問は、どのようにして単一のフレームを解析するのかということです。私はドキュメントを読んでいて、 iFrameExtractorを見てきました(フレームをデコードするのであまり役に立ちません)。FFMPEG-AVFormatのmov.cを使用することになっているときは正しく理解できたと思いますが、よくわかりません。

編集:私は今このようにしようとしています:

  1. わずかに縮小されたinit関数iiFrameExtractorを実行して、.movファイルでビデオストリームを検索します。

  2. 次のようなフレームのデータを取得します。

    AVPacket packet;
    av_read_frame(pFormatCtx, &packet);
    NSData *frame;
    if(packet.stream_index == videoStream){
        frame = [NSData dataWithBytes:packet.data length:packet.size];
    }
    videoStream++;
    av_free_packet(&packet);
    return frame;
    

次に、それをNSOperationのサブクラスに渡し、アップロードを待機するために保持されます。しかし、EXC_BAD_ACCを受け取りました。フレームからデータをコピーするときに、何か問題がありますか?何か案は。NSData* frame(nonatomic、retain)-propertyを使用してクラス変数を設定しようとすると、EXC_...が取得されます。(合成行にEXC_BAD_ACCと表示されます)

4

3 に答える 3

1

私は以下を使用して、movファイルから各フレームを解析します。

-(NSData *)nextFrame {
    AVPacket packet;
    NSData *frame = nil;

    while(!frame && av_read_frame(pFormatCtx, &packet)>=0) {

        if(packet.stream_index == streamNo) {
            frame = [[[NSData alloc] initWithBytes:packet.data length:packet.size] autorelease];
        }
        av_free_packet(&packet);
    }
    return frame;
}

av_read_frameはフレームを検証しないため注意してください。ただし、これはデコードステップで行われます。これは、返される「フレーム」に、実際のフレームの一部ではない追加情報が含まれている可能性があることを意味します。

AVFormatContext*pFormatCtxおよびAVCodecContext*pCodecCtxを初期化するには、次のコードを使用します(MartinBöhmeのサンプルコードから派生していると思います)。

    AVCodec *pCodec;

    // Register all formats and codecs
    av_register_all();

    // Open video file
    if(avformat_open_input(&pFormatCtx, [moviePath cStringUsingEncoding:NSASCIIStringEncoding], NULL, NULL)!=0)
        goto initError; // Couldn't open file

    // Retrieve stream information
    if(avformat_find_stream_info(pFormatCtx,NULL)<0)
        goto initError; // Couldn't find stream information

    // Find the video stream
    streamNo = -1;
    for(int i=0; i<pFormatCtx->nb_streams; i++){
        if(pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO)
        {
            streamNo = i;
            break;
        }
    }
    if(streamNo == -1)
        goto initError; // Didn't find a video stream

    // Get a pointer to the codec context for the video stream
    pCodecCtx=pFormatCtx->streams[streamNo]->codec;

    // Find the decoder for the video stream
    pCodec=avcodec_find_decoder(pCodecCtx->codec_id);
    if(pCodec==NULL)
        goto initError; // Codec not found

    // Open codec
    if(avcodec_open2(pCodecCtx, pCodec, NULL)<0)
        goto initError; // Could not open codec

    return self;

initError:
    NSLog(@"initError in VideoFrameExtractor");
    [self release];
    return nil;

これが将来誰かに役立つことを願っています。

于 2011-08-18T12:49:35.763 に答える
0

libavcodec/libavformatの使用に関するかなり良いチュートリアルがここにあります。あなたが興味を持っているように聞こえるビットは、DoSomethingWithTheImage()彼らが実装されていないままにした機能です。

于 2011-08-15T11:37:24.750 に答える
0

H264をiOSにストリーミングする場合は、セグメント化されたストリーミング(別名アップルライブストリーミング)が必要です。

これがオープンソースプロジェクトです:http ://code.google.com/p/httpsegmenter/

于 2011-08-15T12:48:56.477 に答える