summaryrefslogtreecommitdiff
path: root/drivers/amvdec_ports/test/vcodec_m2m_test.c (plain)
blob: bec040b424299eeff291c6d1e1300af0d4f79f6b
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 case AV_CODEC_ID_MPEG1VIDEO:
161 forced_codec_name = "mpeg1_v4l2m2m";
162 break;
163 case AV_CODEC_ID_MPEG2VIDEO:
164 forced_codec_name = "mpeg2_v4l2m2m";
165 break;
166 case AV_CODEC_ID_VC1:
167 forced_codec_name = "vc1_v4l2m2m";
168 break;
169 case AV_CODEC_ID_H263:
170 forced_codec_name = "h263_v4l2m2m";
171 break;
172 case AV_CODEC_ID_MPEG4:
173 forced_codec_name = "mpeg4_v4l2m2m";
174 break;
175 case AV_CODEC_ID_MJPEG:
176 forced_codec_name = "mjpeg_v4l2m2m";
177 break;
178 }
179
180 codec = avcodec_find_decoder_by_name(forced_codec_name);
181 if (!codec) {
182 fprintf(stderr, "Unsupported codec with id %d for input stream %d\n",
183 stream->codecpar->codec_id, stream->index);
184 goto out;
185 }
186
187 dec_ctx = avcodec_alloc_context3(codec);
188 if (!dec_ctx) {
189 fprintf(stderr, "Could not allocate video codec context\n");
190 goto out;
191 }
192
193 err = avcodec_parameters_to_context(dec_ctx, stream->codecpar);
194 if (err < 0) {
195 fprintf(stderr, "Could not set paras to context\n");
196 goto out;
197 }
198
199 av_codec_set_pkt_timebase(dec_ctx, stream->time_base);
200 dec_ctx->framerate = stream->avg_frame_rate;
201
202 if (avcodec_open2(dec_ctx, codec, NULL) < 0) {
203 fprintf(stderr, "Could not open codec for input stream %d\n",
204 stream->index);
205 goto out;
206 }
207
208 printf("fmt ctx: %p, stream: %p, video st idx: %d, num: %d\n",
209 ic, stream, vst_idx, ic->nb_streams);
210 printf("format: %s\n",ic->iformat->name);
211
212 ic->flags |= AVFMT_FLAG_GENPTS;
213 ic->debug = 0xff;
214
215 //if (ic->pb)
216 // ic->pb->eof_reached = 0;
217
218 frame = av_frame_alloc();
219 if (!frame) {
220 fprintf(stderr, "Could not allocate video frame\n");
221 goto out;
222 }
223
224 for (;;) {
225 ret = av_read_frame(ic, pkt);
226 if (ret < 0) {
227 if (ret == AVERROR_EOF || avio_feof(ic->pb)) {
228 printf("read data end, ret: %d.\n", ret);
229 break;
230 }
231
232 if (ic->pb && ic->pb->error)
233 break;
234
235 printf("read data fail, ret: %d.\n", ret);
236 continue;
237 }
238
239 if (pkt->stream_index == vctx->vst_idx) {
240 //packet_queue_put(&is->audioq, pkt);
241 //printf("read video data size: %d.\n", pkt->size);
242 if (pkt->size)
243 decode(dec_ctx, frame, pkt, DUMP_DIR);
244 }
245
246 av_packet_unref(pkt);
247
248 usleep(8 * 1000);
249 }
250
251 /* flush the decoder */
252 decode(dec_ctx, frame, NULL, DUMP_DIR);
253out:
254 if (dec_ctx)
255 avcodec_free_context(&dec_ctx);
256
257 if (frame)
258 av_frame_free(&frame);
259
260 if (ic) {
261 avformat_close_input(&ic);
262 avformat_free_context(ic);
263 }
264
265 printf("read thread exit.\n");
266
267 pthread_mutex_lock(&vctx->pthread_mutex);
268 pthread_cond_signal(&vctx->pthread_cond);
269 pthread_mutex_unlock(&vctx->pthread_mutex);
270
271 return NULL;
272}
273
274static int open_input_file(const char *filename)
275{
276 int ret;
277 VcodecCtx *vctx;
278 pthread_t pid = pthread_self();
279
280 vctx = av_mallocz(sizeof(VcodecCtx));
281 if (!vctx)
282 return -1;
283
284 vctx->filename = av_strdup(filename);
285 if (!vctx->filename) {
286 av_free(vctx);
287 return -1;
288 }
289
290 pthread_mutex_init(&vctx->pthread_mutex, NULL);
291 pthread_cond_init(&vctx->pthread_cond, NULL);
292
293 ret = pthread_create(&vctx->tid, NULL, read_thread, (void *)vctx);
294 if (ret == 0) {
295 pthread_setname_np(pid, "read_thread");
296
297 pthread_mutex_lock(&vctx->pthread_mutex);
298 pthread_cond_wait(&vctx->pthread_cond, &vctx->pthread_mutex);
299 pthread_join(vctx->tid, NULL);
300 pthread_mutex_unlock(&vctx->pthread_mutex);
301 }
302
303 av_free(vctx->filename);
304 av_free(vctx);
305
306 printf("creat the read thread, ret: %d.\n", ret);
307
308 return 0;
309}
310
311int main(int argc, char **argv)
312{
313 int ret;
314 const char *filename;
315 int log_level = 0;
316
317 if (argc < 2) {
318 fprintf(stderr, "Usage: %s <input file>\n ==> %s/frame-123\n", argv[0], DUMP_DIR);
319 exit(0);
320 }
321
322 filename = argv[1];
323 if (argv[2]) {
324 if (!strcmp(argv[2], "dump"))
325 dump = 1;
326 else
327 log_level = atoi(argv[2]);
328 }
329
330 mkdir(DUMP_DIR, 0664);
331
332 /*set debug level*/
333 av_log_set_level(log_level); //AV_LOG_DEBUG
334
335 /* register all the codecs */
336 avcodec_register_all();
337
338 ret = open_input_file(filename);
339 if (ret < 0)
340 fprintf(stderr, "open input file fail.\n");
341
342 return 0;
343}
344