1/* 2 * Copyright (c) 2001 Fabrice Bellard 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a copy 5 * of this software and associated documentation files (the "Software"), to deal 6 * in the Software without restriction, including without limitation the rights 7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 * copies of the Software, and to permit persons to whom the Software is 9 * furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 * THE SOFTWARE. 21 */ 22 23/** 24 * @file 25 * video decoding with libavcodec API example 26 * 27 * @example decode_video.c 28 */ 29 30#include <stdio.h> 31#include <stdlib.h> 32#include <string.h> 33 34#include <libavcodec/avcodec.h> 35 36#define INBUF_SIZE 4096 37 38static void pgm_save(unsigned char *buf, int wrap, int xsize, int ysize, 39 char *filename) 40{ 41 FILE *f; 42 int i; 43 44 f = fopen(filename,"wb"); 45 fprintf(f, "P5\n%d %d\n%d\n", xsize, ysize, 255); 46 for (i = 0; i < ysize; i++) 47 fwrite(buf + i * wrap, 1, xsize, f); 48 fclose(f); 49} 50 51static void decode(AVCodecContext *dec_ctx, AVFrame *frame, AVPacket *pkt, 52 const char *filename) 53{ 54 char buf[1024]; 55 int ret; 56 57 ret = avcodec_send_packet(dec_ctx, pkt); 58 if (ret < 0) { 59 fprintf(stderr, "Error sending a packet for decoding\n"); 60 exit(1); 61 } 62 63 while (ret >= 0) { 64 ret = avcodec_receive_frame(dec_ctx, frame); 65 if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) 66 return; 67 else if (ret < 0) { 68 fprintf(stderr, "Error during decoding\n"); 69 exit(1); 70 } 71 72 printf("saving frame %3d\n", dec_ctx->frame_number); 73 fflush(stdout); 74 75 /* the picture is allocated by the decoder. no need to 76 free it */ 77 snprintf(buf, sizeof(buf), "%s-%d", filename, dec_ctx->frame_number); 78 pgm_save(frame->data[0], frame->linesize[0], 79 frame->width, frame->height, buf); 80 } 81} 82 83int main(int argc, char **argv) 84{ 85 const char *filename, *outfilename; 86 const AVCodec *codec; 87 AVCodecParserContext *parser; 88 AVCodecContext *c= NULL; 89 FILE *f; 90 AVFrame *frame; 91 uint8_t inbuf[INBUF_SIZE + AV_INPUT_BUFFER_PADDING_SIZE]; 92 uint8_t *data; 93 size_t data_size; 94 int ret; 95 int eof; 96 AVPacket *pkt; 97 98 if (argc <= 2) { 99 fprintf(stderr, "Usage: %s <input file> <output file>\n" 100 "And check your input file is encoded by mpeg1video please.\n", argv[0]); 101 exit(0); 102 } 103 filename = argv[1]; 104 outfilename = argv[2]; 105 106 pkt = av_packet_alloc(); 107 if (!pkt) 108 exit(1); 109 110 /* set end of buffer to 0 (this ensures that no overreading happens for damaged MPEG streams) */ 111 memset(inbuf + INBUF_SIZE, 0, AV_INPUT_BUFFER_PADDING_SIZE); 112 113 /* find the MPEG-1 video decoder */ 114 codec = avcodec_find_decoder(AV_CODEC_ID_MPEG1VIDEO); 115 if (!codec) { 116 fprintf(stderr, "Codec not found\n"); 117 exit(1); 118 } 119 120 parser = av_parser_init(codec->id); 121 if (!parser) { 122 fprintf(stderr, "parser not found\n"); 123 exit(1); 124 } 125 126 c = avcodec_alloc_context3(codec); 127 if (!c) { 128 fprintf(stderr, "Could not allocate video codec context\n"); 129 exit(1); 130 } 131 132 /* For some codecs, such as msmpeg4 and mpeg4, width and height 133 MUST be initialized there because this information is not 134 available in the bitstream. */ 135 136 /* open it */ 137 if (avcodec_open2(c, codec, NULL) < 0) { 138 fprintf(stderr, "Could not open codec\n"); 139 exit(1); 140 } 141 142 f = fopen(filename, "rb"); 143 if (!f) { 144 fprintf(stderr, "Could not open %s\n", filename); 145 exit(1); 146 } 147 148 frame = av_frame_alloc(); 149 if (!frame) { 150 fprintf(stderr, "Could not allocate video frame\n"); 151 exit(1); 152 } 153 154 do { 155 /* read raw data from the input file */ 156 data_size = fread(inbuf, 1, INBUF_SIZE, f); 157 if (ferror(f)) 158 break; 159 eof = !data_size; 160 161 /* use the parser to split the data into frames */ 162 data = inbuf; 163 while (data_size > 0 || eof) { 164 ret = av_parser_parse2(parser, c, &pkt->data, &pkt->size, 165 data, data_size, AV_NOPTS_VALUE, AV_NOPTS_VALUE, 0); 166 if (ret < 0) { 167 fprintf(stderr, "Error while parsing\n"); 168 exit(1); 169 } 170 data += ret; 171 data_size -= ret; 172 173 if (pkt->size) 174 decode(c, frame, pkt, outfilename); 175 else if (eof) 176 break; 177 } 178 } while (!eof); 179 180 /* flush the decoder */ 181 decode(c, frame, NULL, outfilename); 182 183 fclose(f); 184 185 av_parser_close(parser); 186 avcodec_free_context(&c); 187 av_frame_free(&frame); 188 av_packet_free(&pkt); 189 190 return 0; 191} 192