* commit '7b1f03477f1a43d2261fbd83e50a4ad90c7f806d': examples/avcodec: split the remaining two examples into separate files Merged-by: Clément Bœsch <u@pkh.me>tags/n3.3
| @@ -1462,9 +1462,10 @@ EXAMPLE_LIST=" | |||
| avio_dir_cmd_example | |||
| avio_reading_example | |||
| decode_audio_example | |||
| decoding_encoding_example | |||
| decode_video_example | |||
| demuxing_decoding_example | |||
| encode_audio_example | |||
| encode_video_example | |||
| extract_mvs_example | |||
| filter_audio_example | |||
| filtering_audio_example | |||
| @@ -3170,9 +3171,10 @@ scale_vaapi_filter_deps="vaapi VAProcPipelineParameterBuffer" | |||
| avio_dir_cmd_deps="avformat avutil" | |||
| avio_reading_deps="avformat avcodec avutil" | |||
| decode_audio_example_deps="avcodec avutil" | |||
| decoding_encoding_example_deps="avcodec avformat avutil" | |||
| decode_video_example_deps="avcodec avutil" | |||
| demuxing_decoding_example_deps="avcodec avformat avutil" | |||
| encode_audio_example_deps="avcodec avutil" | |||
| encode_video_example_deps="avcodec avutil" | |||
| extract_mvs_example_deps="avcodec avformat avutil" | |||
| filter_audio_example_deps="avfilter avutil" | |||
| filtering_audio_example_deps="avfilter avcodec avformat avutil" | |||
| @@ -39,9 +39,10 @@ DOCS = $(DOCS-yes) | |||
| DOC_EXAMPLES-$(CONFIG_AVIO_DIR_CMD_EXAMPLE) += avio_dir_cmd | |||
| DOC_EXAMPLES-$(CONFIG_AVIO_READING_EXAMPLE) += avio_reading | |||
| DOC_EXAMPLES-$(CONFIG_DECODE_AUDIO_EXAMPLE) += decode_audio | |||
| DOC_EXAMPLES-$(CONFIG_DECODING_ENCODING_EXAMPLE) += decoding_encoding | |||
| DOC_EXAMPLES-$(CONFIG_DECODE_VIDEO_EXAMPLE) += decode_video | |||
| DOC_EXAMPLES-$(CONFIG_DEMUXING_DECODING_EXAMPLE) += demuxing_decoding | |||
| DOC_EXAMPLES-$(CONFIG_ENCODE_AUDIO_EXAMPLE) += encode_audio | |||
| DOC_EXAMPLES-$(CONFIG_ENCODE_VIDEO_EXAMPLE) += encode_video | |||
| DOC_EXAMPLES-$(CONFIG_EXTRACT_MVS_EXAMPLE) += extract_mvs | |||
| DOC_EXAMPLES-$(CONFIG_FILTER_AUDIO_EXAMPLE) += filter_audio | |||
| DOC_EXAMPLES-$(CONFIG_FILTERING_AUDIO_EXAMPLE) += filtering_audio | |||
| @@ -1,9 +1,10 @@ | |||
| /avio_dir_cmd | |||
| /avio_reading | |||
| /decode_audio | |||
| /decoding_encoding | |||
| /decode_video | |||
| /demuxing_decoding | |||
| /encode_audio | |||
| /encode_video | |||
| /extract_mvs | |||
| /filter_audio | |||
| /filtering_audio | |||
| @@ -14,9 +14,10 @@ LDLIBS := $(shell pkg-config --libs $(FFMPEG_LIBS)) $(LDLIBS) | |||
| EXAMPLES= avio_dir_cmd \ | |||
| avio_reading \ | |||
| decode_audio \ | |||
| decoding_encoding \ | |||
| decode_video \ | |||
| demuxing_decoding \ | |||
| encode_audio \ | |||
| encode_video \ | |||
| extract_mvs \ | |||
| filtering_video \ | |||
| filtering_audio \ | |||
| @@ -0,0 +1,182 @@ | |||
| /* | |||
| * Copyright (c) 2001 Fabrice Bellard | |||
| * | |||
| * Permission is hereby granted, free of charge, to any person obtaining a copy | |||
| * of this software and associated documentation files (the "Software"), to deal | |||
| * in the Software without restriction, including without limitation the rights | |||
| * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |||
| * copies of the Software, and to permit persons to whom the Software is | |||
| * furnished to do so, subject to the following conditions: | |||
| * | |||
| * The above copyright notice and this permission notice shall be included in | |||
| * all copies or substantial portions of the Software. | |||
| * | |||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |||
| * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |||
| * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |||
| * THE SOFTWARE. | |||
| */ | |||
| /** | |||
| * @file | |||
| * video decoding with libavcodec API example | |||
| * | |||
| * @example decode_video.c | |||
| */ | |||
| #include <stdio.h> | |||
| #include <stdlib.h> | |||
| #include <string.h> | |||
| #include <libavcodec/avcodec.h> | |||
| #define INBUF_SIZE 4096 | |||
| static void pgm_save(unsigned char *buf, int wrap, int xsize, int ysize, | |||
| char *filename) | |||
| { | |||
| FILE *f; | |||
| int i; | |||
| f = fopen(filename,"w"); | |||
| fprintf(f, "P5\n%d %d\n%d\n", xsize, ysize, 255); | |||
| for (i = 0; i < ysize; i++) | |||
| fwrite(buf + i * wrap, 1, xsize, f); | |||
| fclose(f); | |||
| } | |||
| static int decode_write_frame(const char *outfilename, AVCodecContext *avctx, | |||
| AVFrame *frame, int *frame_count, AVPacket *pkt, int last) | |||
| { | |||
| int len, got_frame; | |||
| char buf[1024]; | |||
| len = avcodec_decode_video2(avctx, frame, &got_frame, pkt); | |||
| if (len < 0) { | |||
| fprintf(stderr, "Error while decoding frame %d\n", *frame_count); | |||
| return len; | |||
| } | |||
| if (got_frame) { | |||
| printf("Saving %sframe %3d\n", last ? "last " : "", *frame_count); | |||
| fflush(stdout); | |||
| /* the picture is allocated by the decoder, no need to free it */ | |||
| snprintf(buf, sizeof(buf), outfilename, *frame_count); | |||
| pgm_save(frame->data[0], frame->linesize[0], | |||
| frame->width, frame->height, buf); | |||
| (*frame_count)++; | |||
| } | |||
| if (pkt->data) { | |||
| pkt->size -= len; | |||
| pkt->data += len; | |||
| } | |||
| return 0; | |||
| } | |||
| int main(int argc, char **argv) | |||
| { | |||
| const char *filename, *outfilename; | |||
| AVCodec *codec; | |||
| AVCodecContext *c= NULL; | |||
| int frame_count; | |||
| FILE *f; | |||
| AVFrame *frame; | |||
| uint8_t inbuf[INBUF_SIZE + AV_INPUT_BUFFER_PADDING_SIZE]; | |||
| AVPacket avpkt; | |||
| if (argc <= 2) { | |||
| fprintf(stderr, "Usage: %s <input file> <output file>\n", argv[0]); | |||
| exit(0); | |||
| } | |||
| filename = argv[1]; | |||
| outfilename = argv[2]; | |||
| avcodec_register_all(); | |||
| av_init_packet(&avpkt); | |||
| /* set end of buffer to 0 (this ensures that no overreading happens for damaged MPEG streams) */ | |||
| memset(inbuf + INBUF_SIZE, 0, AV_INPUT_BUFFER_PADDING_SIZE); | |||
| /* find the MPEG-1 video decoder */ | |||
| codec = avcodec_find_decoder(AV_CODEC_ID_MPEG1VIDEO); | |||
| if (!codec) { | |||
| fprintf(stderr, "Codec not found\n"); | |||
| exit(1); | |||
| } | |||
| c = avcodec_alloc_context3(codec); | |||
| if (!c) { | |||
| fprintf(stderr, "Could not allocate video codec context\n"); | |||
| exit(1); | |||
| } | |||
| if (codec->capabilities & AV_CODEC_CAP_TRUNCATED) | |||
| c->flags |= AV_CODEC_FLAG_TRUNCATED; // we do not send complete frames | |||
| /* For some codecs, such as msmpeg4 and mpeg4, width and height | |||
| MUST be initialized there because this information is not | |||
| available in the bitstream. */ | |||
| /* open it */ | |||
| if (avcodec_open2(c, codec, NULL) < 0) { | |||
| fprintf(stderr, "Could not open codec\n"); | |||
| exit(1); | |||
| } | |||
| f = fopen(filename, "rb"); | |||
| if (!f) { | |||
| fprintf(stderr, "Could not open %s\n", filename); | |||
| exit(1); | |||
| } | |||
| frame = av_frame_alloc(); | |||
| if (!frame) { | |||
| fprintf(stderr, "Could not allocate video frame\n"); | |||
| exit(1); | |||
| } | |||
| frame_count = 0; | |||
| for (;;) { | |||
| avpkt.size = fread(inbuf, 1, INBUF_SIZE, f); | |||
| if (avpkt.size == 0) | |||
| break; | |||
| /* NOTE1: some codecs are stream based (mpegvideo, mpegaudio) | |||
| and this is the only method to use them because you cannot | |||
| know the compressed data size before analysing it. | |||
| BUT some other codecs (msmpeg4, mpeg4) are inherently frame | |||
| based, so you must call them with all the data for one | |||
| frame exactly. You must also initialize 'width' and | |||
| 'height' before initializing them. */ | |||
| /* NOTE2: some codecs allow the raw parameters (frame size, | |||
| sample rate) to be changed at any frame. We handle this, so | |||
| you should also take care of it */ | |||
| /* here, we use a stream based decoder (mpeg1video), so we | |||
| feed decoder and see if it could decode a frame */ | |||
| avpkt.data = inbuf; | |||
| while (avpkt.size > 0) | |||
| if (decode_write_frame(outfilename, c, frame, &frame_count, &avpkt, 0) < 0) | |||
| exit(1); | |||
| } | |||
| /* Some codecs, such as MPEG, transmit the I- and P-frame with a | |||
| latency of one frame. You must do the following to have a | |||
| chance to get the last frame of the video. */ | |||
| avpkt.data = NULL; | |||
| avpkt.size = 0; | |||
| decode_write_frame(outfilename, c, frame, &frame_count, &avpkt, 1); | |||
| fclose(f); | |||
| avcodec_free_context(&c); | |||
| av_frame_free(&frame); | |||
| return 0; | |||
| } | |||
| @@ -1,361 +0,0 @@ | |||
| /* | |||
| * Copyright (c) 2001 Fabrice Bellard | |||
| * | |||
| * Permission is hereby granted, free of charge, to any person obtaining a copy | |||
| * of this software and associated documentation files (the "Software"), to deal | |||
| * in the Software without restriction, including without limitation the rights | |||
| * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |||
| * copies of the Software, and to permit persons to whom the Software is | |||
| * furnished to do so, subject to the following conditions: | |||
| * | |||
| * The above copyright notice and this permission notice shall be included in | |||
| * all copies or substantial portions of the Software. | |||
| * | |||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |||
| * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |||
| * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |||
| * THE SOFTWARE. | |||
| */ | |||
| /** | |||
| * @file | |||
| * libavcodec API use example. | |||
| * | |||
| * @example decoding_encoding.c | |||
| * Note that libavcodec only handles codecs (MPEG, MPEG-4, etc...), | |||
| * not file formats (AVI, VOB, MP4, MOV, MKV, MXF, FLV, MPEG-TS, MPEG-PS, etc...). | |||
| * See library 'libavformat' for the format handling | |||
| */ | |||
| #include <math.h> | |||
| #include <libavutil/opt.h> | |||
| #include <libavcodec/avcodec.h> | |||
| #include <libavutil/channel_layout.h> | |||
| #include <libavutil/common.h> | |||
| #include <libavutil/imgutils.h> | |||
| #include <libavutil/mathematics.h> | |||
| #include <libavutil/samplefmt.h> | |||
| #define INBUF_SIZE 4096 | |||
| /* | |||
| * Video encoding example | |||
| */ | |||
| static void video_encode_example(const char *filename, int codec_id) | |||
| { | |||
| AVCodec *codec; | |||
| AVCodecContext *c= NULL; | |||
| int i, ret, x, y, got_output; | |||
| FILE *f; | |||
| AVFrame *frame; | |||
| AVPacket pkt; | |||
| uint8_t endcode[] = { 0, 0, 1, 0xb7 }; | |||
| printf("Encode video file %s\n", filename); | |||
| /* find the video encoder */ | |||
| codec = avcodec_find_encoder(codec_id); | |||
| if (!codec) { | |||
| fprintf(stderr, "Codec not found\n"); | |||
| exit(1); | |||
| } | |||
| c = avcodec_alloc_context3(codec); | |||
| if (!c) { | |||
| fprintf(stderr, "Could not allocate video codec context\n"); | |||
| exit(1); | |||
| } | |||
| /* put sample parameters */ | |||
| c->bit_rate = 400000; | |||
| /* resolution must be a multiple of two */ | |||
| c->width = 352; | |||
| c->height = 288; | |||
| /* frames per second */ | |||
| c->time_base = (AVRational){1,25}; | |||
| /* emit one intra frame every ten frames | |||
| * check frame pict_type before passing frame | |||
| * to encoder, if frame->pict_type is AV_PICTURE_TYPE_I | |||
| * then gop_size is ignored and the output of encoder | |||
| * will always be I frame irrespective to gop_size | |||
| */ | |||
| c->gop_size = 10; | |||
| c->max_b_frames = 1; | |||
| c->pix_fmt = AV_PIX_FMT_YUV420P; | |||
| if (codec_id == AV_CODEC_ID_H264) | |||
| av_opt_set(c->priv_data, "preset", "slow", 0); | |||
| /* open it */ | |||
| if (avcodec_open2(c, codec, NULL) < 0) { | |||
| fprintf(stderr, "Could not open codec\n"); | |||
| exit(1); | |||
| } | |||
| f = fopen(filename, "wb"); | |||
| if (!f) { | |||
| fprintf(stderr, "Could not open %s\n", filename); | |||
| exit(1); | |||
| } | |||
| frame = av_frame_alloc(); | |||
| if (!frame) { | |||
| fprintf(stderr, "Could not allocate video frame\n"); | |||
| exit(1); | |||
| } | |||
| frame->format = c->pix_fmt; | |||
| frame->width = c->width; | |||
| frame->height = c->height; | |||
| /* the image can be allocated by any means and av_image_alloc() is | |||
| * just the most convenient way if av_malloc() is to be used */ | |||
| ret = av_image_alloc(frame->data, frame->linesize, c->width, c->height, | |||
| c->pix_fmt, 32); | |||
| if (ret < 0) { | |||
| fprintf(stderr, "Could not allocate raw picture buffer\n"); | |||
| exit(1); | |||
| } | |||
| /* encode 1 second of video */ | |||
| for (i = 0; i < 25; i++) { | |||
| av_init_packet(&pkt); | |||
| pkt.data = NULL; // packet data will be allocated by the encoder | |||
| pkt.size = 0; | |||
| fflush(stdout); | |||
| /* prepare a dummy image */ | |||
| /* Y */ | |||
| for (y = 0; y < c->height; y++) { | |||
| for (x = 0; x < c->width; x++) { | |||
| frame->data[0][y * frame->linesize[0] + x] = x + y + i * 3; | |||
| } | |||
| } | |||
| /* Cb and Cr */ | |||
| for (y = 0; y < c->height/2; y++) { | |||
| for (x = 0; x < c->width/2; x++) { | |||
| frame->data[1][y * frame->linesize[1] + x] = 128 + y + i * 2; | |||
| frame->data[2][y * frame->linesize[2] + x] = 64 + x + i * 5; | |||
| } | |||
| } | |||
| frame->pts = i; | |||
| /* encode the image */ | |||
| ret = avcodec_encode_video2(c, &pkt, frame, &got_output); | |||
| if (ret < 0) { | |||
| fprintf(stderr, "Error encoding frame\n"); | |||
| exit(1); | |||
| } | |||
| if (got_output) { | |||
| printf("Write frame %3d (size=%5d)\n", i, pkt.size); | |||
| fwrite(pkt.data, 1, pkt.size, f); | |||
| av_packet_unref(&pkt); | |||
| } | |||
| } | |||
| /* get the delayed frames */ | |||
| for (got_output = 1; got_output; i++) { | |||
| fflush(stdout); | |||
| ret = avcodec_encode_video2(c, &pkt, NULL, &got_output); | |||
| if (ret < 0) { | |||
| fprintf(stderr, "Error encoding frame\n"); | |||
| exit(1); | |||
| } | |||
| if (got_output) { | |||
| printf("Write frame %3d (size=%5d)\n", i, pkt.size); | |||
| fwrite(pkt.data, 1, pkt.size, f); | |||
| av_packet_unref(&pkt); | |||
| } | |||
| } | |||
| /* add sequence end code to have a real MPEG file */ | |||
| fwrite(endcode, 1, sizeof(endcode), f); | |||
| fclose(f); | |||
| avcodec_free_context(&c); | |||
| av_freep(&frame->data[0]); | |||
| av_frame_free(&frame); | |||
| printf("\n"); | |||
| } | |||
| /* | |||
| * Video decoding example | |||
| */ | |||
| static void pgm_save(unsigned char *buf, int wrap, int xsize, int ysize, | |||
| char *filename) | |||
| { | |||
| FILE *f; | |||
| int i; | |||
| f = fopen(filename,"w"); | |||
| fprintf(f, "P5\n%d %d\n%d\n", xsize, ysize, 255); | |||
| for (i = 0; i < ysize; i++) | |||
| fwrite(buf + i * wrap, 1, xsize, f); | |||
| fclose(f); | |||
| } | |||
| static int decode_write_frame(const char *outfilename, AVCodecContext *avctx, | |||
| AVFrame *frame, int *frame_count, AVPacket *pkt, int last) | |||
| { | |||
| int len, got_frame; | |||
| char buf[1024]; | |||
| len = avcodec_decode_video2(avctx, frame, &got_frame, pkt); | |||
| if (len < 0) { | |||
| fprintf(stderr, "Error while decoding frame %d\n", *frame_count); | |||
| return len; | |||
| } | |||
| if (got_frame) { | |||
| printf("Saving %sframe %3d\n", last ? "last " : "", *frame_count); | |||
| fflush(stdout); | |||
| /* the picture is allocated by the decoder, no need to free it */ | |||
| snprintf(buf, sizeof(buf), outfilename, *frame_count); | |||
| pgm_save(frame->data[0], frame->linesize[0], | |||
| frame->width, frame->height, buf); | |||
| (*frame_count)++; | |||
| } | |||
| if (pkt->data) { | |||
| pkt->size -= len; | |||
| pkt->data += len; | |||
| } | |||
| return 0; | |||
| } | |||
| static void video_decode_example(const char *outfilename, const char *filename) | |||
| { | |||
| AVCodec *codec; | |||
| AVCodecContext *c= NULL; | |||
| int frame_count; | |||
| FILE *f; | |||
| AVFrame *frame; | |||
| uint8_t inbuf[INBUF_SIZE + AV_INPUT_BUFFER_PADDING_SIZE]; | |||
| AVPacket avpkt; | |||
| av_init_packet(&avpkt); | |||
| /* set end of buffer to 0 (this ensures that no overreading happens for damaged MPEG streams) */ | |||
| memset(inbuf + INBUF_SIZE, 0, AV_INPUT_BUFFER_PADDING_SIZE); | |||
| printf("Decode video file %s to %s\n", filename, outfilename); | |||
| /* find the MPEG-1 video decoder */ | |||
| codec = avcodec_find_decoder(AV_CODEC_ID_MPEG1VIDEO); | |||
| if (!codec) { | |||
| fprintf(stderr, "Codec not found\n"); | |||
| exit(1); | |||
| } | |||
| c = avcodec_alloc_context3(codec); | |||
| if (!c) { | |||
| fprintf(stderr, "Could not allocate video codec context\n"); | |||
| exit(1); | |||
| } | |||
| if (codec->capabilities & AV_CODEC_CAP_TRUNCATED) | |||
| c->flags |= AV_CODEC_FLAG_TRUNCATED; // we do not send complete frames | |||
| /* For some codecs, such as msmpeg4 and mpeg4, width and height | |||
| MUST be initialized there because this information is not | |||
| available in the bitstream. */ | |||
| /* open it */ | |||
| if (avcodec_open2(c, codec, NULL) < 0) { | |||
| fprintf(stderr, "Could not open codec\n"); | |||
| exit(1); | |||
| } | |||
| f = fopen(filename, "rb"); | |||
| if (!f) { | |||
| fprintf(stderr, "Could not open %s\n", filename); | |||
| exit(1); | |||
| } | |||
| frame = av_frame_alloc(); | |||
| if (!frame) { | |||
| fprintf(stderr, "Could not allocate video frame\n"); | |||
| exit(1); | |||
| } | |||
| frame_count = 0; | |||
| for (;;) { | |||
| avpkt.size = fread(inbuf, 1, INBUF_SIZE, f); | |||
| if (avpkt.size == 0) | |||
| break; | |||
| /* NOTE1: some codecs are stream based (mpegvideo, mpegaudio) | |||
| and this is the only method to use them because you cannot | |||
| know the compressed data size before analysing it. | |||
| BUT some other codecs (msmpeg4, mpeg4) are inherently frame | |||
| based, so you must call them with all the data for one | |||
| frame exactly. You must also initialize 'width' and | |||
| 'height' before initializing them. */ | |||
| /* NOTE2: some codecs allow the raw parameters (frame size, | |||
| sample rate) to be changed at any frame. We handle this, so | |||
| you should also take care of it */ | |||
| /* here, we use a stream based decoder (mpeg1video), so we | |||
| feed decoder and see if it could decode a frame */ | |||
| avpkt.data = inbuf; | |||
| while (avpkt.size > 0) | |||
| if (decode_write_frame(outfilename, c, frame, &frame_count, &avpkt, 0) < 0) | |||
| exit(1); | |||
| } | |||
| /* Some codecs, such as MPEG, transmit the I- and P-frame with a | |||
| latency of one frame. You must do the following to have a | |||
| chance to get the last frame of the video. */ | |||
| avpkt.data = NULL; | |||
| avpkt.size = 0; | |||
| decode_write_frame(outfilename, c, frame, &frame_count, &avpkt, 1); | |||
| fclose(f); | |||
| avcodec_free_context(&c); | |||
| av_frame_free(&frame); | |||
| printf("\n"); | |||
| } | |||
| int main(int argc, char **argv) | |||
| { | |||
| const char *output_type; | |||
| /* register all the codecs */ | |||
| avcodec_register_all(); | |||
| if (argc < 2) { | |||
| printf("usage: %s output_type\n" | |||
| "API example program to decode/encode a media stream with libavcodec.\n" | |||
| "This program generates a synthetic stream and encodes it to a file\n" | |||
| "named test.h264, test.mp2 or test.mpg depending on output_type.\n" | |||
| "The encoded stream is then decoded and written to a raw data output.\n" | |||
| "output_type must be chosen between 'h264', 'mp2', 'mpg'.\n", | |||
| argv[0]); | |||
| return 1; | |||
| } | |||
| output_type = argv[1]; | |||
| if (!strcmp(output_type, "h264")) { | |||
| video_encode_example("test.h264", AV_CODEC_ID_H264); | |||
| } else if (!strcmp(output_type, "mpg")) { | |||
| video_encode_example("test.mpg", AV_CODEC_ID_MPEG1VIDEO); | |||
| video_decode_example("test%02d.pgm", "test.mpg"); | |||
| } else { | |||
| fprintf(stderr, "Invalid output type '%s', choose between 'h264', 'mp2', or 'mpg'\n", | |||
| output_type); | |||
| return 1; | |||
| } | |||
| return 0; | |||
| } | |||
| @@ -0,0 +1,187 @@ | |||
| /* | |||
| * Copyright (c) 2001 Fabrice Bellard | |||
| * | |||
| * Permission is hereby granted, free of charge, to any person obtaining a copy | |||
| * of this software and associated documentation files (the "Software"), to deal | |||
| * in the Software without restriction, including without limitation the rights | |||
| * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |||
| * copies of the Software, and to permit persons to whom the Software is | |||
| * furnished to do so, subject to the following conditions: | |||
| * | |||
| * The above copyright notice and this permission notice shall be included in | |||
| * all copies or substantial portions of the Software. | |||
| * | |||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |||
| * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |||
| * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |||
| * THE SOFTWARE. | |||
| */ | |||
| /** | |||
| * @file | |||
| * video encoding with libavcodec API example | |||
| * | |||
| * @example encode_video.c | |||
| */ | |||
| #include <stdio.h> | |||
| #include <stdlib.h> | |||
| #include <string.h> | |||
| #include <libavcodec/avcodec.h> | |||
| #include <libavutil/opt.h> | |||
| #include <libavutil/imgutils.h> | |||
| int main(int argc, char **argv) | |||
| { | |||
| const char *filename, *codec_name; | |||
| AVCodec *codec; | |||
| AVCodecContext *c= NULL; | |||
| int i, ret, x, y, got_output; | |||
| FILE *f; | |||
| AVFrame *frame; | |||
| AVPacket pkt; | |||
| uint8_t endcode[] = { 0, 0, 1, 0xb7 }; | |||
| if (argc <= 2) { | |||
| fprintf(stderr, "Usage: %s <output file> <codec name>\n", argv[0]); | |||
| exit(0); | |||
| } | |||
| filename = argv[1]; | |||
| codec_name = argv[2]; | |||
| avcodec_register_all(); | |||
| /* find the mpeg1video encoder */ | |||
| codec = avcodec_find_encoder_by_name(codec_name); | |||
| if (!codec) { | |||
| fprintf(stderr, "Codec not found\n"); | |||
| exit(1); | |||
| } | |||
| c = avcodec_alloc_context3(codec); | |||
| if (!c) { | |||
| fprintf(stderr, "Could not allocate video codec context\n"); | |||
| exit(1); | |||
| } | |||
| /* put sample parameters */ | |||
| c->bit_rate = 400000; | |||
| /* resolution must be a multiple of two */ | |||
| c->width = 352; | |||
| c->height = 288; | |||
| /* frames per second */ | |||
| c->time_base = (AVRational){1,25}; | |||
| /* emit one intra frame every ten frames | |||
| * check frame pict_type before passing frame | |||
| * to encoder, if frame->pict_type is AV_PICTURE_TYPE_I | |||
| * then gop_size is ignored and the output of encoder | |||
| * will always be I frame irrespective to gop_size | |||
| */ | |||
| c->gop_size = 10; | |||
| c->max_b_frames = 1; | |||
| c->pix_fmt = AV_PIX_FMT_YUV420P; | |||
| if (codec->id == AV_CODEC_ID_H264) | |||
| av_opt_set(c->priv_data, "preset", "slow", 0); | |||
| /* open it */ | |||
| if (avcodec_open2(c, codec, NULL) < 0) { | |||
| fprintf(stderr, "Could not open codec\n"); | |||
| exit(1); | |||
| } | |||
| f = fopen(filename, "wb"); | |||
| if (!f) { | |||
| fprintf(stderr, "Could not open %s\n", filename); | |||
| exit(1); | |||
| } | |||
| frame = av_frame_alloc(); | |||
| if (!frame) { | |||
| fprintf(stderr, "Could not allocate video frame\n"); | |||
| exit(1); | |||
| } | |||
| frame->format = c->pix_fmt; | |||
| frame->width = c->width; | |||
| frame->height = c->height; | |||
| /* the image can be allocated by any means and av_image_alloc() is | |||
| * just the most convenient way if av_malloc() is to be used */ | |||
| ret = av_image_alloc(frame->data, frame->linesize, c->width, c->height, | |||
| c->pix_fmt, 32); | |||
| if (ret < 0) { | |||
| fprintf(stderr, "Could not allocate raw picture buffer\n"); | |||
| exit(1); | |||
| } | |||
| /* encode 1 second of video */ | |||
| for (i = 0; i < 25; i++) { | |||
| av_init_packet(&pkt); | |||
| pkt.data = NULL; // packet data will be allocated by the encoder | |||
| pkt.size = 0; | |||
| fflush(stdout); | |||
| /* prepare a dummy image */ | |||
| /* Y */ | |||
| for (y = 0; y < c->height; y++) { | |||
| for (x = 0; x < c->width; x++) { | |||
| frame->data[0][y * frame->linesize[0] + x] = x + y + i * 3; | |||
| } | |||
| } | |||
| /* Cb and Cr */ | |||
| for (y = 0; y < c->height/2; y++) { | |||
| for (x = 0; x < c->width/2; x++) { | |||
| frame->data[1][y * frame->linesize[1] + x] = 128 + y + i * 2; | |||
| frame->data[2][y * frame->linesize[2] + x] = 64 + x + i * 5; | |||
| } | |||
| } | |||
| frame->pts = i; | |||
| /* encode the image */ | |||
| ret = avcodec_encode_video2(c, &pkt, frame, &got_output); | |||
| if (ret < 0) { | |||
| fprintf(stderr, "Error encoding frame\n"); | |||
| exit(1); | |||
| } | |||
| if (got_output) { | |||
| printf("Write frame %3d (size=%5d)\n", i, pkt.size); | |||
| fwrite(pkt.data, 1, pkt.size, f); | |||
| av_packet_unref(&pkt); | |||
| } | |||
| } | |||
| /* get the delayed frames */ | |||
| for (got_output = 1; got_output; i++) { | |||
| fflush(stdout); | |||
| ret = avcodec_encode_video2(c, &pkt, NULL, &got_output); | |||
| if (ret < 0) { | |||
| fprintf(stderr, "Error encoding frame\n"); | |||
| exit(1); | |||
| } | |||
| if (got_output) { | |||
| printf("Write frame %3d (size=%5d)\n", i, pkt.size); | |||
| fwrite(pkt.data, 1, pkt.size, f); | |||
| av_packet_unref(&pkt); | |||
| } | |||
| } | |||
| /* add sequence end code to have a real MPEG file */ | |||
| fwrite(endcode, 1, sizeof(endcode), f); | |||
| fclose(f); | |||
| avcodec_free_context(&c); | |||
| av_freep(&frame->data[0]); | |||
| av_frame_free(&frame); | |||
| return 0; | |||
| } | |||