Rob*_*Rye 5 parsing quicktime ffmpeg video-processing mpeg-4
我正在尝试从.mov文件解析H.264帧.我想我已经得出结论,来自AVFormat的mov.c - FFMPEG的一部分是要走的路.但mov.c是未注释代码旁边约2600行.我正在寻找FFMPEG的使用示例,尤其是解析任何文件类型的结构.无论是MPEG4还是Quicktime Movie都没关系,因为它们在结构上非常相似.
如果没有现有的例子(我找不到)可能有人使用过它并且可以给我几行代码,或者解释如何开始?
我正在尝试做的事情:我使用AVCaptureSession从摄像机捕获样本,然后在H264中对这些样本进行编码,并借助AVAssetsWriter,AVAssetsWriterInput和AVAssetsWriterInputPixelBufferAdaptor将其写入文件.原因是我无法直接访问硬件H264编码,因为苹果不允许这样做.我现在需要做的事情(我认为不确定)是解析出来的:
.mov文件中的" mdat "-atom(电影数据,我认为可能不止一个).那么" 视频 "-atom然后在视频原子内(视频数据样本,可能有不止一个).我想我会相信几个原子是帧.这些将是"avc1"类型(这是H264的类型).请纠正我,因为我很确定我还没有正确地完成这一切.
我的问题是,我将如何解析单帧.我一直在阅读文档并查看了iFrameExtractor(由于它对帧进行解码,因此不是很有帮助).我想我理解正确的话时,我应该使用mov.c从FFMPEG-AVFormat,但我不知道.
编辑:我现在正在尝试这样:
我运行稍微减少的init函数i iFrameExtractor,它在.mov文件中找到了视频流.
我得到框架的数据,如下所示:
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;
Run Code Online (Sandbox Code Playgroud)然后我将它传递给NSOperation的子类,在那里保留等待上传.但我收到一个EXC_BAD_ACC,从框架中复制数据时我做错了什么?有任何想法吗.当我尝试NSData* frame使用其(非原子,保留)属性设置类变量时,我得到了EXC _... (它在合成行上说EXC_BAD_ACC)
我使用以下内容来解析 mov 文件中的每一帧。
\n\n-(NSData *)nextFrame {\n AVPacket packet;\n NSData *frame = nil;\n\n while(!frame && av_read_frame(pFormatCtx, &packet)>=0) {\n\n if(packet.stream_index == streamNo) {\n frame = [[[NSData alloc] initWithBytes:packet.data length:packet.size] autorelease];\n }\n av_free_packet(&packet);\n }\n return frame;\n}\nRun Code Online (Sandbox Code Playgroud)\n\n尽管请注意,因为 av_read_frame 不会验证帧,但这是在解码步骤中完成的。这意味着返回的“帧”可能包含不属于实际帧的额外信息。
\n\n要初始化 AVFormatContext *pFormatCtx 和 AVCodecContext *pCodecCtx 我使用此代码(我相信它源自 Martin B\xc3\xb6hme\ 的示例代码):
\n\n AVCodec *pCodec;\n\n // Register all formats and codecs\n av_register_all();\n\n // Open video file\n if(avformat_open_input(&pFormatCtx, [moviePath cStringUsingEncoding:NSASCIIStringEncoding], NULL, NULL)!=0)\n goto initError; // Couldn\'t open file\n\n // Retrieve stream information\n if(avformat_find_stream_info(pFormatCtx,NULL)<0)\n goto initError; // Couldn\'t find stream information\n\n // Find the video stream\n streamNo = -1;\n for(int i=0; i<pFormatCtx->nb_streams; i++){\n if(pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO)\n {\n streamNo = i;\n break;\n }\n }\n if(streamNo == -1)\n goto initError; // Didn\'t find a video stream\n\n // Get a pointer to the codec context for the video stream\n pCodecCtx=pFormatCtx->streams[streamNo]->codec;\n\n // Find the decoder for the video stream\n pCodec=avcodec_find_decoder(pCodecCtx->codec_id);\n if(pCodec==NULL)\n goto initError; // Codec not found\n\n // Open codec\n if(avcodec_open2(pCodecCtx, pCodec, NULL)<0)\n goto initError; // Could not open codec\n\n return self;\n\ninitError:\n NSLog(@"initError in VideoFrameExtractor");\n [self release];\n return nil;\nRun Code Online (Sandbox Code Playgroud)\n\n希望这对将来的人有帮助。
\n