2011-08-15 2 views
5

Я пытаюсь разобрать кадры H.264 из файла .mov. Думаю, я пришел к выводу, что mov.c из AVFormat-части FFMPEG - это путь. Но mov.c составляет ~ 2600 строк рядом с незарегистрированным кодом. Я ищу примеры использования FFMPEG, особенно для синтаксического анализа структуры любого типа файла. неважно, является ли это MPEG4 или Quicktime Movie, поскольку они очень похожи по своей структуре.Анализ по кадру из .mov с использованием ffmpeg

Если нет существующих примеров (я не могу найти их), возможно, кто-то использовал его и может дать мне пару строк кода или объяснить, как начать работу?

То, что я пытаюсь сделать: я использую AVCaptureSession для захвата образцов с видеокамеры, эти образцы затем кодируются в H264 и записываются в файл с помощью AVAssetsWriter, AVAssetsWriterInput и AVAssetsWriterInputPixelBufferAdaptor. Причина в том, что я не могу получить доступ к аппаратной кодировке H264 напрямую, так как Apple этого не допустит. Что теперь мне нужно сделать (я думаю, не уверен) это разобрать:

The «MDAT» -атом (данные Movie, может быть больше, чем один я думаю) из файла .mov. , тогда «vide» -атом, а затем в виде-атоме (образец видеоданных может быть более одного). Я думаю, что будет несколько атомов, которых я считаю рамками. они будут иметь тип «avc1» (это тип для H264). Пожалуйста, исправьте меня в этом, потому что я абсолютно уверен, что я не получил все это правильно, но.

Мой вопрос в том, как я могу разобрать отдельные кадры. Я читал the documentation и смотрел iFrameExtractor (что не очень полезно, так как он декодирует кадры). Я думаю, что правильно понял, когда я должен использовать mov.c из FFMPEG-AVFormat, но я не уверен.

Edit: Я сейчас пытаюсь так:

  1. я бегу немного уменьшенную функцию инициализации я iFrameExtractor, который находит видеопоток в .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, неужели я что-то делаю неправильно при копировании данных из фрейма? есть идеи. Я получаю EXC _..., когда пытаюсь установить переменную класса NSData* frame, используя ее (неатомное, сохраняющее) свойство. (он говорит EXC_BAD_ACC в строке синтеза)

+0

mov.c не поможет вам с достижением цели. Если вам нужна помощь по разборке MOV/MP4, это может быть удобно. Еще одна удобная библиотека, когда ситуация становится грубой [mp4v2] (http://code.google.com/p/mp4v2/). В основном вам придется писать это самостоятельно. Никакая библиотека не собирается выполнять работу по разным причинам. –

+0

@Steve McFarlin, спасибо, у вас есть какие-то советы по чтению, кроме qt-документации, чтобы понять всю структуру mov-файла, потому что у меня действительно возникают проблемы с захватом всего этого, правильно ли это, что атом даже не должны быть в определенном порядке? какой, по вашему мнению, было проще всего работать с mov или mp4? –

+0

@Steve McFarlin, я думаю, вы видели проект iFrameExtractor. это также по сути тот же код, что и в учебнике Мартина Бёма (например, на dranger.com). в следующей функции кадра они используют только av_read_frame, а затем декодируют это. не будет ли AVPacket изменен av_read_frame закодированным H264-кадром? –

ответ

1

я использую следующий для разбора каждого кадра из файла мов.

-(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 Я использую этот код (который я считаю, является производным от кода примера Мартина Беме в):

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; 

надеюсь, что это поможет кому-то в будущем.

0

Существует неплохой учебник по использованию libavcodec/libavformat here. Бит кажется, что вас интересует функция DoSomethingWithTheImage(), которую они оставили незавершенной.

+0

Я хочу сырые данные H.264, поэтому я могу собрать кадры в mov на стороне сервера позже. Я уже рассматривал этот пример и не мог понять, должен ли я пропускать шаг декодирования? и просто сохраните 'rawData = package.data'? что происходит, когда я декодирую? тогда я иду из стандарта H.264? –

+1

Вы оба читаете и пишите .mov? что ты тогда делаешь? –

+0

@yi_H Я разбираю файл .mov во время записи, чтобы отправить кадры H264 на сервер, где я снова их собираю. это единственный способ передать H264 в режиме реального времени с iOS, насколько я понимаю. –

0

Если вы перекачиваете H264 в iOS, вам нужна сегментированная потоковая передача (например, прямая трансляция Apple).

Вот открытый проект источника: http://code.google.com/p/httpsegmenter/

+1

Я собираюсь переходить с iOS. используя AVCaptureSession и AVAssetsWriter для записи с камеры на файл. то я хочу проанализировать файл, чтобы получить кадры H264 и загрузить их в файл. У меня есть все, включая HTTP-пакеты для загрузки. мне нужен способ доступа к кадрам в файле .mov, доступ к необработанным данным кадра. возможно, он будет работать с примером, опубликованным в другом ответе. Я пытаюсь сейчас, если у вас есть другое предложение о том, как я могу заставить его работать, пожалуйста, поделитесь им :) –

+0

вы хотите сбросить аудио канал? вы хотите использовать другой контейнер? Я все еще не понимаю. –

+0

Я понял, что другой ответ не будет работать, так как он декодирует кадр, поэтому он больше не будет закодирован в H264. Мне нужно немедленно извлечь кадры из видеопотока без декодирования –

Смежные вопросы