• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * This file is part of FFmpeg.
3  *
4  * FFmpeg is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * FFmpeg is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with FFmpeg; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18 
19 /* shared code for simple demux/decode tools */
20 
21 #include <stdlib.h>
22 #include <string.h>
23 
24 #include "decode_simple.h"
25 
26 #include "libavformat/avformat.h"
27 
28 #include "libavcodec/avcodec.h"
29 #include "libavcodec/packet.h"
30 
31 #include "libavutil/dict.h"
32 #include "libavutil/error.h"
33 #include "libavutil/frame.h"
34 
decode_read(DecodeContext * dc,int flush)35 static int decode_read(DecodeContext *dc, int flush)
36 {
37     const int ret_done = flush ? AVERROR_EOF : AVERROR(EAGAIN);
38     int ret = 0;
39 
40     while (ret >= 0 &&
41            (dc->max_frames == 0 || dc->decoder->frame_number < dc->max_frames)) {
42         ret = avcodec_receive_frame(dc->decoder, dc->frame);
43         if (ret < 0) {
44             if (ret == AVERROR_EOF) {
45                 int err = dc->process_frame(dc, NULL);
46                 if (err < 0)
47                     return err;
48             }
49 
50             return (ret == ret_done) ? 0 : ret;
51         }
52 
53         ret = dc->process_frame(dc, dc->frame);
54         av_frame_unref(dc->frame);
55         if (ret < 0)
56             return ret;
57 
58         if (dc->max_frames && dc->decoder->frame_number == dc->max_frames)
59             return 1;
60     }
61 
62     return (dc->max_frames == 0 || dc->decoder->frame_number < dc->max_frames) ? 0 : 1;
63 }
64 
ds_run(DecodeContext * dc)65 int ds_run(DecodeContext *dc)
66 {
67     int ret;
68 
69     ret = avcodec_open2(dc->decoder, NULL, &dc->decoder_opts);
70     if (ret < 0)
71         return ret;
72 
73     while (ret >= 0) {
74         ret = av_read_frame(dc->demuxer, dc->pkt);
75         if (ret < 0)
76             goto flush;
77         if (dc->pkt->stream_index != dc->stream->index) {
78             av_packet_unref(dc->pkt);
79             continue;
80         }
81 
82         ret = avcodec_send_packet(dc->decoder, dc->pkt);
83         if (ret < 0) {
84             fprintf(stderr, "Error decoding: %d\n", ret);
85             return ret;
86         }
87         av_packet_unref(dc->pkt);
88 
89         ret = decode_read(dc, 0);
90         if (ret < 0) {
91             fprintf(stderr, "Error decoding: %d\n", ret);
92             return ret;
93         } else if (ret > 0)
94             return 0;
95     }
96 
97 flush:
98     avcodec_send_packet(dc->decoder, NULL);
99     ret = decode_read(dc, 1);
100     if (ret < 0) {
101         fprintf(stderr, "Error flushing: %d\n", ret);
102         return ret;
103     }
104 
105     return 0;
106 }
107 
ds_free(DecodeContext * dc)108 void ds_free(DecodeContext *dc)
109 {
110     av_dict_free(&dc->decoder_opts);
111 
112     av_frame_free(&dc->frame);
113     av_packet_free(&dc->pkt);
114 
115     avcodec_free_context(&dc->decoder);
116     avformat_close_input(&dc->demuxer);
117 }
118 
ds_open(DecodeContext * dc,const char * url,int stream_idx)119 int ds_open(DecodeContext *dc, const char *url, int stream_idx)
120 {
121     const AVCodec *codec;
122     int ret;
123 
124     memset(dc, 0, sizeof(*dc));
125 
126     dc->pkt   = av_packet_alloc();
127     dc->frame = av_frame_alloc();
128     if (!dc->pkt || !dc->frame) {
129         ret = AVERROR(ENOMEM);
130         goto fail;
131     }
132 
133     ret = avformat_open_input(&dc->demuxer, url, NULL, NULL);
134     if (ret < 0) {
135         fprintf(stderr, "Error opening input file: %d\n", ret);
136         return ret;
137     }
138 
139     if (stream_idx < 0 || stream_idx >= dc->demuxer->nb_streams)
140         return AVERROR(EINVAL);
141 
142     dc->stream = dc->demuxer->streams[stream_idx];
143 
144     codec = avcodec_find_decoder(dc->stream->codecpar->codec_id);
145     if (!codec)
146         return AVERROR_DECODER_NOT_FOUND;
147 
148     dc->decoder = avcodec_alloc_context3(codec);
149     if (!dc->decoder)
150         return AVERROR(ENOMEM);
151 
152     return 0;
153 
154 fail:
155     ds_free(dc);
156     return ret;
157 }
158