FFmpeg
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
api-codec-param-test.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015 Matthieu Bouron <matthieu.bouron stupeflix.com>
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 #include <stdio.h>
24 #include "libavformat/avformat.h"
25 #include "libavutil/pixdesc.h"
26 #include "libavcodec/internal.h"
27 #include "libavutil/avassert.h"
28 #include "libavutil/opt.h"
29 
31 {
32  int ret = 0;
33  int got_frame = 0;
34  AVFrame *frame = NULL;
35  int skip_frame = codec_ctx->skip_frame;
36 
37  if (!avcodec_is_open(codec_ctx)) {
38  const AVCodec *codec = avcodec_find_decoder(codec_ctx->codec_id);
39 
40  ret = avcodec_open2(codec_ctx, codec, NULL);
41  if (ret < 0) {
42  av_log(codec_ctx, AV_LOG_ERROR, "Failed to open codec\n");
43  goto end;
44  }
45  }
46 
47  frame = av_frame_alloc();
48  if (!frame) {
49  av_log(NULL, AV_LOG_ERROR, "Failed to allocate frame\n");
50  goto end;
51  }
52 
53  if (!decode && avpriv_codec_get_cap_skip_frame_fill_param(codec_ctx->codec)) {
54  codec_ctx->skip_frame = AVDISCARD_ALL;
55  }
56 
57  do {
58  ret = avcodec_decode_video2(codec_ctx, frame, &got_frame, pkt);
59  av_assert0(decode || (!decode && !got_frame));
60  if (ret < 0)
61  break;
62  pkt->data += ret;
63  pkt->size -= ret;
64 
65  if (got_frame) {
66  break;
67  }
68  } while (pkt->size > 0);
69 
70 end:
71  codec_ctx->skip_frame = skip_frame;
72 
73  av_frame_free(&frame);
74  return ret;
75 }
76 
78 {
79  int ret = 0;
80  int i, done = 0;
81  AVPacket pkt;
82 
83  av_init_packet(&pkt);
84 
85  while (!done) {
86  AVCodecContext *codec_ctx = NULL;
87  AVStream *st;
88 
89  if ((ret = av_read_frame(fmt_ctx, &pkt)) < 0) {
90  av_log(fmt_ctx, AV_LOG_ERROR, "Failed to read frame\n");
91  goto end;
92  }
93 
94  st = fmt_ctx->streams[pkt.stream_index];
95  codec_ctx = st->codec;
96 
97  /* Writing to AVStream.codec_info_nb_frames must not be done by
98  * user applications. It is done here for testing purposing as
99  * find_video_stream_info tries to mimic avformat_find_stream_info
100  * which writes to this field.
101  * */
102  if (codec_ctx->codec_type != AVMEDIA_TYPE_VIDEO ||
103  st->codec_info_nb_frames++ > 0) {
104  av_packet_unref(&pkt);
105  continue;
106  }
107 
108  ret = try_decode_video_frame(codec_ctx, &pkt, decode);
109  if (ret < 0) {
110  av_log(fmt_ctx, AV_LOG_ERROR, "Failed to decode video frame\n");
111  goto end;
112  }
113 
114  av_packet_unref(&pkt);
115 
116  /* check if all video streams have demuxed a packet */
117  done = 1;
118  for (i = 0; i < fmt_ctx->nb_streams; i++) {
119  st = fmt_ctx->streams[i];
120  codec_ctx = st->codec;
121 
122  if (codec_ctx->codec_type != AVMEDIA_TYPE_VIDEO)
123  continue;
124 
125  done &= st->codec_info_nb_frames > 0;
126  }
127  }
128 
129 end:
130  av_packet_unref(&pkt);
131 
132  /* close all codecs opened in try_decode_video_frame */
133  for (i = 0; i < fmt_ctx->nb_streams; i++) {
134  AVStream *st = fmt_ctx->streams[i];
135  avcodec_close(st->codec);
136  }
137 
138  return ret < 0;
139 }
140 
142 {
143  int i;
144 
145  for (i = 0; i < fmt_ctx->nb_streams; i++) {
146  const AVOption *opt = NULL;
147  const AVStream *st = fmt_ctx->streams[i];
148  AVCodecContext *codec_ctx = st->codec;
149 
150  printf("stream=%d, decode=%d\n", i, decode);
151  while (opt = av_opt_next(codec_ctx, opt)) {
152  uint8_t *str;
153 
154  if (opt->type == AV_OPT_TYPE_CONST)
155  continue;
156 
157  if (!strcmp(opt->name, "frame_number"))
158  continue;
159 
160  if (av_opt_get(codec_ctx, opt->name, 0, &str) >= 0) {
161  printf(" %s=%s\n", opt->name, str);
162  av_free(str);
163  }
164  }
165  }
166 }
167 
168 static int open_and_probe_video_streams(AVFormatContext **fmt_ctx, const char *filename, int decode)
169 {
170  int ret = 0;
171 
172  ret = avformat_open_input(fmt_ctx, filename, NULL, NULL);
173  if (ret < 0) {
174  av_log(NULL, AV_LOG_ERROR, "Failed to open input '%s'", filename);
175  goto end;
176  }
177 
178  ret = find_video_stream_info(*fmt_ctx, decode);
179  if (ret < 0) {
180  goto end;
181  }
182 
183  dump_video_streams(*fmt_ctx, decode);
184 
185 end:
186  return ret;
187 }
188 
189 static int check_video_streams(const AVFormatContext *fmt_ctx1, const AVFormatContext *fmt_ctx2)
190 {
191  int i;
192  int ret = 0;
193 
194  av_assert0(fmt_ctx1->nb_streams == fmt_ctx2->nb_streams);
195  for (i = 0; i < fmt_ctx1->nb_streams; i++) {
196  const AVOption *opt = NULL;
197  const AVStream *st1 = fmt_ctx1->streams[i];
198  const AVStream *st2 = fmt_ctx2->streams[i];
199  AVCodecContext *codec_ctx1 = st1->codec;
200  AVCodecContext *codec_ctx2 = st2->codec;
201 
202  if (codec_ctx1->codec_type != AVMEDIA_TYPE_VIDEO)
203  continue;
204 
205  while (opt = av_opt_next(codec_ctx1, opt)) {
206  uint8_t *str1 = NULL, *str2 = NULL;
207 
208  if (opt->type == AV_OPT_TYPE_CONST)
209  continue;
210 
211  if (!strcmp(opt->name, "frame_number"))
212  continue;
213 
214  av_assert0(av_opt_get(codec_ctx1, opt->name, 0, &str1) >= 0);
215  av_assert0(av_opt_get(codec_ctx2, opt->name, 0, &str2) >= 0);
216  if (strcmp(str1, str2)) {
217  av_log(NULL, AV_LOG_ERROR, "Field %s differs: %s %s", opt->name, str1, str2);
218  ret = AVERROR(EINVAL);
219  }
220  av_free(str1);
221  av_free(str2);
222  }
223  }
224 
225  return ret;
226 }
227 
228 int main(int argc, char* argv[])
229 {
230  int ret = 0;
232  AVFormatContext *fmt_ctx_no_decode = NULL;
233 
234  av_register_all();
235 
236  if (argc < 2) {
237  av_log(NULL, AV_LOG_ERROR, "Usage: %s <input>\n", argv[0]);
238  return -1;
239  }
240 
241  if ((ret = open_and_probe_video_streams(&fmt_ctx_no_decode, argv[1], 0)) < 0) {
242  av_log(NULL, AV_LOG_ERROR, "Failed to probe '%s' without frame decoding\n", argv[1]);
243  goto end;
244  }
245 
246  if ((ret = open_and_probe_video_streams(&fmt_ctx, argv[1], 1)) < 0) {
247  av_log(NULL, AV_LOG_ERROR, "Failed to probe '%s' with frame decoding\n", argv[1]);
248  goto end;
249  }
250 
251  ret = check_video_streams(fmt_ctx, fmt_ctx_no_decode);
252 
253 end:
254  avformat_close_input(&fmt_ctx);
255  avformat_close_input(&fmt_ctx_no_decode);
256 
257  return ret;
258 }
#define NULL
Definition: coverity.c:32
const struct AVCodec * codec
Definition: avcodec.h:1685
This structure describes decoded (raw) audio or video data.
Definition: frame.h:184
AVOption.
Definition: opt.h:245
int avpriv_codec_get_cap_skip_frame_fill_param(const AVCodec *codec)
Definition: utils.c:1196
int main(int argc, char *argv[])
static AVFormatContext * fmt_ctx
int size
Definition: avcodec.h:1602
discard all
Definition: avcodec.h:787
static AVPacket pkt
AVCodec.
Definition: avcodec.h:3600
Format I/O context.
Definition: avformat.h:1338
enum AVDiscard skip_frame
Skip decoding for selected frames.
Definition: avcodec.h:3301
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:37
const char * name
Definition: opt.h:246
uint8_t
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
Definition: frame.c:145
AVOptions.
static int find_video_stream_info(AVFormatContext *fmt_ctx, int decode)
static av_cold int end(AVCodecContext *avctx)
Definition: avrndec.c:90
AVStream ** streams
A list of all streams in the file.
Definition: avformat.h:1406
static AVFrame * frame
uint8_t * data
Definition: avcodec.h:1601
#define av_log(a,...)
int avcodec_close(AVCodecContext *avctx)
Close a given AVCodecContext and free all the data associated with it (but not the AVCodecContext its...
Definition: utils.c:3023
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
static int try_decode_video_frame(AVCodecContext *codec_ctx, AVPacket *pkt, int decode)
#define AVERROR(e)
Definition: error.h:43
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:158
int avcodec_is_open(AVCodecContext *s)
Definition: utils.c:4006
simple assert() macros that are a bit more flexible than ISO C assert().
const AVOption * av_opt_next(const void *obj, const AVOption *last)
Iterate over all AVOptions belonging to obj.
Definition: opt.c:45
unsigned int nb_streams
Number of elements in AVFormatContext.streams.
Definition: avformat.h:1394
Stream structure.
Definition: avformat.h:889
enum AVMediaType codec_type
Definition: avcodec.h:1684
attribute_deprecated int avcodec_decode_video2(AVCodecContext *avctx, AVFrame *picture, int *got_picture_ptr, const AVPacket *avpkt)
Decode the video frame of size avpkt->size from avpkt->data into picture.
Definition: utils.c:2213
enum AVCodecID codec_id
Definition: avcodec.h:1693
static int open_and_probe_video_streams(AVFormatContext **fmt_ctx, const char *filename, int decode)
main external API structure.
Definition: avcodec.h:1676
AVCodec * avcodec_find_decoder(enum AVCodecID id)
Find a registered decoder with a matching codec ID.
Definition: utils.c:3127
void av_packet_unref(AVPacket *pkt)
Wipe the packet.
Definition: avpacket.c:567
static void dump_video_streams(const AVFormatContext *fmt_ctx, int decode)
int avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options)
Initialize the AVCodecContext to use the given AVCodec.
Definition: utils.c:1241
int av_read_frame(AVFormatContext *s, AVPacket *pkt)
Return the next frame of a stream.
Definition: utils.c:1676
Main libavformat public API header.
static int check_video_streams(const AVFormatContext *fmt_ctx1, const AVFormatContext *fmt_ctx2)
common internal api header.
void av_init_packet(AVPacket *pkt)
Initialize optional fields of a packet with default values.
Definition: avpacket.c:33
void avformat_close_input(AVFormatContext **s)
Close an opened input AVFormatContext.
Definition: utils.c:4165
int av_opt_get(void *obj, const char *name, int search_flags, uint8_t **out_val)
Definition: opt.c:732
#define av_free(p)
enum AVOptionType type
Definition: opt.h:259
int codec_info_nb_frames
Number of frames that have been demuxed during av_find_stream_info()
Definition: avformat.h:1073
int avformat_open_input(AVFormatContext **ps, const char *url, AVInputFormat *fmt, AVDictionary **options)
Open an input stream and read the header.
Definition: utils.c:503
static int decode(AVCodecContext *avctx, AVFrame *frame, int *got_frame, AVPacket *pkt)
Definition: ffmpeg.c:2035
int stream_index
Definition: avcodec.h:1603
This structure stores compressed data.
Definition: avcodec.h:1578
void av_register_all(void)
Initialize libavformat and register all the muxers, demuxers and protocols.
Definition: allformats.c:44