summaryrefslogtreecommitdiff
path: root/drivers/amvdec_ports/test/vcodec_m2m_test.c (plain)
blob: 0110676b57eccb2a6d6931ad0425929be9ddcc25
1/*
2* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
3*
4* This program is free software; you can redistribute it and/or modify
5* it under the terms of the GNU General Public License as published by
6* the Free Software Foundation; either version 2 of the License, or
7* (at your option) any later version.
8*
9* This program is distributed in the hope that it will be useful, but WITHOUT
10* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12* more details.
13*
14* You should have received a copy of the GNU General Public License along
15* with this program; if not, write to the Free Software Foundation, Inc.,
16* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17*
18* Description:
19*/
20#include <stdio.h>
21#include <stdlib.h>
22#include <string.h>
23#include <libavcodec/avcodec.h>
24#include <libavformat/avformat.h>
25#include <pthread.h>
26#include <unistd.h>
27#include <sys/stat.h>
28#include <pthread.h>
29
30#define INBUF_SIZE (4096)
31#define DUMP_DIR "/data/video_frames"
32static int dump;
33
34typedef struct VcodecCtx {
35 AVFormatContext *fmt_ctx;
36 AVStream *stream;
37 int nb_streams;
38 int vst_idx;
39 char *filename;
40 pthread_t tid;
41 pthread_mutex_t pthread_mutex;
42 pthread_cond_t pthread_cond;
43} VcodecCtx;
44
45static void dump_yuv(AVFrame *frame, char *filename)
46{
47 FILE *f;
48
49 printf("name: %s, resolution: %dx%d, size: %d\n",
50 filename, frame->width, frame->height,
51 frame->buf[0]->size + frame->buf[1]->size);
52
53 f = fopen(filename,"w+");
54
55 fwrite(frame->buf[0]->data, 1, frame->buf[0]->size, f);
56 fwrite(frame->buf[1]->data, 1, frame->buf[1]->size, f);
57
58 fclose(f);
59}
60
61static void decode(AVCodecContext *dec_ctx, AVFrame *frame, AVPacket *pkt,
62 const char *filename)
63{
64 char buf[1024];
65 int ret;
66
67 ret = avcodec_send_packet(dec_ctx, pkt);
68 if (ret < 0) {
69 fprintf(stderr, "Error sending a packet for decoding\n");
70 return;
71 }
72
73 while (ret >= 0) {
74 ret = avcodec_receive_frame(dec_ctx, frame);
75 if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
76 return;
77 else if (ret < 0) {
78 fprintf(stderr, "Error during decoding, ret: %s\n", av_err2str(ret));
79 break;
80 }
81
82 //fprintf(stderr, "saving frame %3d\n", dec_ctx->frame_number);
83 fflush(stdout);
84
85 /* the picture is allocated by the decoder. no need to free it */
86 snprintf(buf, sizeof(buf), "%s/frame-%d", filename, dec_ctx->frame_number);
87
88 if (dump)
89 dump_yuv(frame, buf);
90 }
91}
92
93static void* read_thread(void *arg)
94{
95 int ret, err;
96 AVFormatContext *ic = NULL;
97 AVCodecContext *dec_ctx = NULL;
98 AVStream *stream = NULL;
99 AVCodec *codec = NULL;
100 AVPacket pkt1, *pkt = &pkt1;
101 AVFrame *frame = NULL;
102 int vst_idx = 0;
103 int has_video = 0;
104 unsigned int st_idx = 0;
105 VcodecCtx *vctx = arg;
106 const char *forced_codec_name = NULL;
107
108 printf("entry read thread, tid: %ld.\n", vctx->tid);
109
110 ic = avformat_alloc_context();
111 if (!ic) {
112 fprintf(stderr, "Could not allocate avformat context.\n");
113 goto out;
114 }
115
116 err = avformat_open_input(&ic, vctx->filename, NULL, NULL);
117 if (err < 0) {
118 fprintf(stderr, "Could not open avformat input.\n");
119 goto out;
120 }
121
122 err = avformat_find_stream_info(ic, NULL);
123 if (err < 0) {
124 fprintf(stderr, "find stream info err.\n");
125 goto out;
126 }
127
128 for (st_idx = 0; st_idx < ic->nb_streams; st_idx++) {
129 AVStream *st = ic->streams[st_idx];
130
131 enum AVMediaType type = st->codecpar->codec_type;
132 st->discard = AVDISCARD_ALL;
133
134 if (type == AVMEDIA_TYPE_VIDEO) {
135 st->discard = AVDISCARD_NONE;
136 vctx->vst_idx = st_idx;
137 has_video = 1;
138 break;
139 }
140 }
141
142 if (!has_video) {
143 fprintf(stderr, "no video stream.\n");
144 goto out;
145 }
146
147 stream = ic->streams[vctx->vst_idx];
148
149 //codec = avcodec_find_decoder(stream->codecpar->codec_id);
150 switch (stream->codecpar->codec_id) {
151 case AV_CODEC_ID_H264:
152 forced_codec_name = "h264_v4l2m2m";
153 break;
154 case AV_CODEC_ID_HEVC:
155 forced_codec_name = "hevc_v4l2m2m";
156 break;
157 case AV_CODEC_ID_VP9:
158 forced_codec_name = "vp9_v4l2m2m";
159 break;
160 }
161
162 codec = avcodec_find_decoder_by_name(forced_codec_name);
163 if (!codec) {
164 fprintf(stderr, "Unsupported codec with id %d for input stream %d\n",
165 stream->codecpar->codec_id, stream->index);
166 goto out;
167 }
168
169 dec_ctx = avcodec_alloc_context3(codec);
170 if (!dec_ctx) {
171 fprintf(stderr, "Could not allocate video codec context\n");
172 goto out;
173 }
174
175 err = avcodec_parameters_to_context(dec_ctx, stream->codecpar);
176 if (err < 0) {
177 fprintf(stderr, "Could not set paras to context\n");
178 goto out;
179 }
180
181 av_codec_set_pkt_timebase(dec_ctx, stream->time_base);
182 dec_ctx->framerate = stream->avg_frame_rate;
183
184 if (avcodec_open2(dec_ctx, codec, NULL) < 0) {
185 fprintf(stderr, "Could not open codec for input stream %d\n",
186 stream->index);
187 goto out;
188 }
189
190 printf("fmt ctx: %p, stream: %p, video st idx: %d, num: %d\n",
191 ic, stream, vst_idx, ic->nb_streams);
192 printf("format: %s\n",ic->iformat->name);
193
194 ic->flags |= AVFMT_FLAG_GENPTS;
195 ic->debug = 0xff;
196
197 //if (ic->pb)
198 // ic->pb->eof_reached = 0;
199
200 frame = av_frame_alloc();
201 if (!frame) {
202 fprintf(stderr, "Could not allocate video frame\n");
203 goto out;
204 }
205
206 for (;;) {
207 ret = av_read_frame(ic, pkt);
208 if (ret < 0) {
209 if (ret == AVERROR_EOF || avio_feof(ic->pb)) {
210 printf("read data end, ret: %d.\n", ret);
211 break;
212 }
213
214 if (ic->pb && ic->pb->error)
215 break;
216
217 printf("read data fail, ret: %d.\n", ret);
218 continue;
219 }
220
221 if (pkt->stream_index == vctx->vst_idx) {
222 //packet_queue_put(&is->audioq, pkt);
223 //printf("read video data size: %d.\n", pkt->size);
224 if (pkt->size)
225 decode(dec_ctx, frame, pkt, DUMP_DIR);
226 }
227
228 av_packet_unref(pkt);
229
230 usleep(8 * 1000);
231 }
232
233 /* flush the decoder */
234 decode(dec_ctx, frame, NULL, DUMP_DIR);
235out:
236 if (dec_ctx)
237 avcodec_free_context(&dec_ctx);
238
239 if (frame)
240 av_frame_free(&frame);
241
242 if (ic) {
243 avformat_close_input(&ic);
244 avformat_free_context(ic);
245 }
246
247 printf("read thread exit.\n");
248
249 pthread_mutex_lock(&vctx->pthread_mutex);
250 pthread_cond_signal(&vctx->pthread_cond);
251 pthread_mutex_unlock(&vctx->pthread_mutex);
252
253 return NULL;
254}
255
256static int open_input_file(const char *filename)
257{
258 int ret;
259 VcodecCtx *vctx;
260 pthread_t pid = pthread_self();
261
262 vctx = av_mallocz(sizeof(VcodecCtx));
263 if (!vctx)
264 return -1;
265
266 vctx->filename = av_strdup(filename);
267 if (!vctx->filename) {
268 av_free(vctx);
269 return -1;
270 }
271
272 pthread_mutex_init(&vctx->pthread_mutex, NULL);
273 pthread_cond_init(&vctx->pthread_cond, NULL);
274
275 ret = pthread_create(&vctx->tid, NULL, read_thread, (void *)vctx);
276 if (ret == 0) {
277 pthread_setname_np(pid, "read_thread");
278
279 pthread_mutex_lock(&vctx->pthread_mutex);
280 pthread_cond_wait(&vctx->pthread_cond, &vctx->pthread_mutex);
281 pthread_join(vctx->tid, NULL);
282 pthread_mutex_unlock(&vctx->pthread_mutex);
283 }
284
285 av_free(vctx->filename);
286 av_free(vctx);
287
288 printf("creat the read thread, ret: %d.\n", ret);
289
290 return 0;
291}
292
293int main(int argc, char **argv)
294{
295 int ret;
296 const char *filename;
297 int log_level = 0;
298
299 if (argc < 2) {
300 fprintf(stderr, "Usage: %s <input file>\n ==> %s/frame-123\n", argv[0], DUMP_DIR);
301 exit(0);
302 }
303
304 filename = argv[1];
305 if (argv[2]) {
306 if (!strcmp(argv[2], "dump"))
307 dump = 1;
308 else
309 log_level = atoi(argv[2]);
310 }
311
312 mkdir(DUMP_DIR, 0664);
313
314 /*set debug level*/
315 av_log_set_level(log_level); //AV_LOG_DEBUG
316
317 /* register all the codecs */
318 avcodec_register_all();
319
320 ret = open_input_file(filename);
321 if (ret < 0)
322 fprintf(stderr, "open input file fail.\n");
323
324 return 0;
325}
326