Skip to content

Instantly share code, notes, and snippets.

@nojima
Created October 1, 2012 17:23
Show Gist options
  • Save nojima/3813164 to your computer and use it in GitHub Desktop.
Save nojima/3813164 to your computer and use it in GitHub Desktop.
(ffmpeg) AVIを読み込んで先頭の5フレームをGray画像として取り出すコード
extern "C" {
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
}
int get_first_video_stream_index(AVFormatContext* format_context)
{
for (int i = 0; i < format_context->nb_streams; ++i) {
if (format_context->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO)
return i;
}
return -1;
}
AVCodec* get_decoder(AVStream* stream)
{
AVCodecContext* codec_context = stream->codec;
AVCodec* codec = avcodec_find_decoder(codec_context->codec_id);
if (codec == nullptr)
return nullptr;
if (avcodec_open(codec_context, codec) < 0)
return nullptr;
return codec;
}
void save_frame(AVFrame* frame, int width, int height, int frameno)
{
char filename[1024];
sprintf(filename, "frame_%03d.pgm", frameno);
FILE* file = fopen(filename, "wb");
if (file == NULL) return;
fprintf(file, "P5\n%d %d\n255\n", width, height);
for (int y = 0; y < height; ++y)
fwrite(frame->data[0] + y * frame->linesize[0], 1, width, file);
fclose(file);
}
int main(int argc, char** argv)
{
av_register_all();
AVFormatContext* format_context = nullptr;
if (avformat_open_input(&format_context, "sample.avi", nullptr, nullptr) != 0)
return -1;
int video_stream_index = get_first_video_stream_index(format_context);
if (video_stream_index == -1)
return -1;
AVStream* video_stream = format_context->streams[video_stream_index];
AVCodecContext* codec_context = video_stream->codec;
AVCodec* codec = get_decoder(video_stream);
AVFrame* frame = avcodec_alloc_frame();
AVFrame* frame_rgb = avcodec_alloc_frame();
int width = codec_context->width, height = codec_context->height;
int num_bytes = avpicture_get_size(PIX_FMT_RGB24, width, height);
uint8_t* buffer = static_cast<uint8_t*>(av_malloc(num_bytes * sizeof(uint8_t)));
avpicture_fill(reinterpret_cast<AVPicture*>(frame_rgb), buffer, PIX_FMT_GRAY8, width, height);
SwsContext* sws_context = sws_getContext(width, height, codec_context->pix_fmt,
width, height, PIX_FMT_GRAY8,
SWS_BILINEAR, nullptr, nullptr, nullptr);
if (sws_context == nullptr)
return -1;
AVPacket packet;
int frameno = 0;
while (av_read_frame(format_context, &packet) >= 0) {
if (packet.stream_index == video_stream_index) {
int finished;
avcodec_decode_video2(codec_context, frame, &finished, &packet);
if (finished) {
sws_scale(sws_context, frame->data, frame->linesize, 0, height,
frame_rgb->data, frame_rgb->linesize);
if (++frameno <= 5)
save_frame(frame_rgb, width, height, frameno);
}
}
av_free_packet(&packet);
}
av_free(buffer);
av_free(frame_rgb);
av_free(frame);
avcodec_close(codec_context);
avformat_close_input(&format_context);
return 0;
}
@nojima
Copy link
Author

nojima commented Oct 1, 2012

参考文献

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment