blob: 5e1de971dcc92e6e7aebe6a804529a6edc27b377 [file] [log] [blame]
Song Zhao1b237602020-02-13 10:58:57 -08001/*
2 * Copyright (c) 2019 Amlogic, Inc. All rights reserved.
3 *
4 * This source code is subject to the terms and conditions defined in the
5 * file 'LICENSE' which is part of this source code package.
6 *
7 * Description:
8 */
9#include <pthread.h>
10#include <stdbool.h>
11#include <libavformat/avformat.h>
12#include "demux.h"
13
14#define H2645(format) ((format) == AV_CODEC_ID_H264 || (format) == AV_CODEC_ID_H265)
15#define WORD_BE(p) ((p[0]<<8) | p[1])
16
17#define HEVC_NAL_TYPE(b) ((b>>1)&0x3F)
18#define HEVC_NAL_VPS 32
19#define HEVC_NAL_SPS 33
20#define HEVC_NAL_PPS 34
21
Song Zhao9be28a32020-06-18 22:02:59 -070022extern int log_level;
Song Zhao1b237602020-02-13 10:58:57 -080023/* ffmpeg data structure */
24static AVStream *video_stream = NULL;
25static AVFormatContext *fmt_ctx = NULL;
26static int video_stream_idx = -1;
27
28/* for h264/265 */
29static int raw_stream;
Song Zhao921fbdc2020-06-12 00:21:57 -070030static int keyframe_seen;
Song Zhao1b237602020-02-13 10:58:57 -080031static int nal_size;
32static uint8_t s_nal_3[3] = {0,0,1};
33static uint8_t s_nal_4[4] = {0,0,0,1};
34
35static struct dmx_cb *dec_cb;
36static pthread_t dmx_t;
37static int thread_quit;
38static struct dmx_v_data v_data;
39static int video_frame_count = 0;
Song Zhao9be28a32020-06-18 22:02:59 -070040static int64_t fake_pts = 0;
Song Zhao1b237602020-02-13 10:58:57 -080041
42static void dump(const char* path, uint8_t *data, int size) {
43 FILE* fd = fopen(path, "wb");
44 if (!fd)
45 return;
46 fwrite(data, 1, size, fd);
47 fflush(fd);
48 fclose(fd);
49}
50
51static int insert_nal() {
52 int size;
53 if (nal_size == 3) {
54 dec_cb->write(s_nal_3, sizeof(s_nal_3));
55 size = 3;
56 } else {
57 dec_cb->write(s_nal_4, sizeof(s_nal_4));
58 size = 4;
59 }
60 return size;
61}
62
63#if 0
64static bool check_nal(uint8_t *data, int size) {
65 if (size < 4)
66 return false;
67 if (nal_size == 3 && data[0] == 0 &&
68 data[1] == 0 && data[2] == 1)
69 return true;
70 if (nal_size == 4 && data[0] == 0 &&
71 data[1] == 0 && data[2] == 0 && data[3] == 1)
72 return true;
73 return false;
74}
75#endif
76
77static int demux_packet(AVPacket* pkt)
78{
79 int decoded = pkt->size;
Song Zhaof781ce52020-06-10 23:44:16 -070080 int64_t pts_us = 0;
81 AVRational ns_r = {1,DMX_SECOND};
Song Zhao1b237602020-02-13 10:58:57 -080082
83 if (pkt->stream_index != video_stream_idx)
84 return decoded;
85
Song Zhao9be28a32020-06-18 22:02:59 -070086 if (pkt->pts != AV_NOPTS_VALUE) {
Song Zhaof781ce52020-06-10 23:44:16 -070087 pts_us = av_rescale_q(pkt->pts, video_stream->time_base, ns_r);
Song Zhao9be28a32020-06-18 22:02:59 -070088 fake_pts = pts_us;
89 } else {
90 pts_us = fake_pts + av_rescale_q(pkt->duration, video_stream->time_base, ns_r);
91 fake_pts = pts_us;
92 }
Song Zhaof781ce52020-06-10 23:44:16 -070093
Song Zhao1b237602020-02-13 10:58:57 -080094 /* video frame */
95 video_frame_count++;
96#ifdef DEBUG_FRAME
Song Zhao9be28a32020-06-18 22:02:59 -070097 printf("video_frame n:%d pts:%lld size:%x\n",
Song Zhao1b237602020-02-13 10:58:57 -080098 video_frame_count,
Song Zhaof781ce52020-06-10 23:44:16 -070099 pts_us, pkt->size);
Song Zhao1b237602020-02-13 10:58:57 -0800100#endif
101
102 /* refer to ffmpeg hevc_mp4toannexb_filter()
103 * and h264_extradata_to_annexb()
104 */
105 if (H2645(video_stream->codecpar->codec_id)) {
106 uint8_t *p = pkt->data;
107 int length_size = nal_size;
108 int nalu_size = 0;
109 int processed = 0;
110
111 /* From raw ES */
112 if (raw_stream) {
113 dec_cb->write(pkt->data, pkt->size);
114 processed = pkt->size;
115 //printf("raw es frame\n");
116 }
117
Song Zhao921fbdc2020-06-12 00:21:57 -0700118 if (!keyframe_seen && !(pkt->flags & AV_PKT_FLAG_KEY)) {
119 printf("drop none I frame at beginning\n");
120 return decoded;
121 }
122 if (!keyframe_seen && (pkt->flags & AV_PKT_FLAG_KEY)) {
123 printf("Got I frame at beginning\n");
124 keyframe_seen = 1;
125 }
Song Zhao1b237602020-02-13 10:58:57 -0800126 /* data inside pkt->data is like:
127 * len0 + data0 + len1 + data1 ... + lenN + dataN
128 * lenX depends on the nal_size
129 */
130 while (processed < pkt->size) {
131 int i;
132
133 for (i = 0; i < length_size; i++)
134 nalu_size = (nalu_size << 8) | (*p++);
135 processed += length_size;
136
137 insert_nal();
138 dec_cb->write(p, nalu_size);
139
140#ifdef DEBUG_FRAME
141 printf("nalu_size(%04x) %02x %02x %02x %02x",
142 nalu_size, p[0], p[1], p[2], p[3]);
143#endif
144
145 p += nalu_size;
146 processed += nalu_size;
147
148#ifdef DEBUG_FRAME
149 printf(" ... %02x %02x %02x %02x\n",
150 *(p-3), *(p-2), *(p-1), *p);
151#endif
152 }
153 } else {
154 dec_cb->write(pkt->data, pkt->size);
155 }
Song Zhaof781ce52020-06-10 23:44:16 -0700156 dec_cb->frame_done(pts_us);
Song Zhao1b237602020-02-13 10:58:57 -0800157
158 return decoded;
159}
160
161static int open_codec_context(int *stream_idx,
162 AVFormatContext *fmt_ctx, enum AVMediaType type)
163{
164 int ret, stream_index;
165
166 ret = av_find_best_stream(fmt_ctx, type, -1, -1, NULL, 0);
167 if (ret < 0) {
168 return ret;
169 } else {
170 stream_index = ret;
171 *stream_idx = stream_index;
172 }
173
174 return 0;
175}
176
177/*
178 * Refer to h264_parse.c ff_h264_decode_extradata()
179 * parse AVCDecoderConfigurationRecord
180 * See MPEG-4 Part 15 "Advanced Video Coding (AVC) file format" section 5.2.4.1 for details.
181 * data will be release outside
182 */
183static int h264_header_parse(uint8_t *data, int size,
184 uint8_t **o_data, int *o_size, int *nal_size) {
185 int i, cnt, nalsize;
186 const uint8_t *p = data;
187 int cur_size = 0;
188
189 if (!data || size <= 0)
190 return -1;
191
192 if (data[0] != 1) {
193 if (size < 7) return -1;
194 if (data[0] == 0 && data[1] == 0 && data[2] == 1)
195 *nal_size = 3;
196 else if (data[0] == 0 && data[1] == 0 && data[3] == 0 && data[4] == 1)
197 *nal_size = 4;
198 else {
199 printf("wrong header\n");
200 return -1;
201 }
202
203 raw_stream = 1;
204 *o_data = (uint8_t *)malloc(4096);
205 if (!*o_data) {
206 printf("oom");
207 return -1;
208 }
209 memcpy(*o_data, data, size);
210 *o_size = size;
211 return 0;
212 }
213
214 if (size < 7) {
215 printf("avcC %d too short\n", size);
216 return -1;
217 }
218
219 *o_data = (uint8_t *)malloc(4096);
220 if (!*o_data) {
221 printf("oom");
222 return -1;
223 }
224
225 // Store right nal length size that will be used to parse all other nals
226 *nal_size = (data[4] & 0x03) + 1;
227
228 // Decode sps from avcC
229 cnt = *(p + 5) & 0x1f; // Number of sps
230 printf("sps cnt:%d\n", cnt);
231
232 //NAL
233 if (cnt) {
234 if (*nal_size == 3) {
235 memcpy(*o_data + cur_size, s_nal_3, 3);
236 cur_size += 3;
237 } else if (*nal_size == 4) {
238 memcpy(*o_data + cur_size, s_nal_4, 4);
239 cur_size += 4;
240 } else {
241 printf("invalid nal size:%d\n", *nal_size);
242 goto err_exit;
243 }
244 }
245
246 p += 6;
247 for (i = 0; i < cnt; i++) {
248 nalsize = WORD_BE(p);
249 p += 2;
250 if (nalsize > size - (p - data))
251 goto err_exit;
252 memcpy(*o_data + cur_size, p, nalsize);
253 p += nalsize;
254 cur_size += nalsize;
255 }
256 // Decode pps from avcC
257 cnt = *(p++); // Number of pps
258 printf("pps cnt:%d\n", cnt);
259
260 //NAL
261 if (cnt) {
262 if (*nal_size == 3) {
263 memcpy(*o_data + cur_size, s_nal_3, 3);
264 cur_size += 3;
265 } else if (*nal_size == 4) {
266 memcpy(*o_data + cur_size, s_nal_4, 4);
267 cur_size += 4;
268 } else {
269 printf("invalid nal size:%d\n", *nal_size);
270 goto err_exit;
271 }
272 }
273
274 for (i = 0; i < cnt; i++) {
275 nalsize = WORD_BE(p);
276 p += 2;
277 if (nalsize > size - (p - data))
278 goto err_exit;
279 memcpy(*o_data + cur_size, p, nalsize);
280 p += nalsize;
281 cur_size += nalsize;
282 }
283 printf("header parse done. cur_size:%d\n", cur_size);
284 *o_size = cur_size;
285 return 0;
286err_exit:
287 free(*o_data);
288 return -2;
289}
290
291/*
292 * Refer to hevc_parse.c ff_hevc_decode_extradata()
293 * hvcC
294 * data will be release outside
295 */
296static int h265_header_parse(uint8_t *data, int size,
297 uint8_t **o_data, int *o_size, int *nal_size) {
298 const uint8_t *p = data;
299 int i, cur_size = 0;
300 int num_arrays;
301
302 if (!data || size <= 0)
303 return -1;
304
305 if (size < 7) {
306 printf("header %d too short\n", size);
307 return -1;
308 }
309
310 *o_data = (uint8_t *)malloc(4096);
311 if (!*o_data) {
312 printf("oom");
313 return -1;
314 }
315
316 if ((!data[0] && !data[1] && data[2] == 1) ||
317 (!data[0] && !data[1] && !data[2] && data[3] == 1)) {
318 /* not hvcC format */
319 *o_size = 0;
320 *nal_size = 4;
321 raw_stream = 1;
322 printf("raw header parse done");
323 return 0;
324 }
325 // Store right nal length size that will be used to parse all other nals
326 p += 21;
327 *nal_size = (*p & 0x03) + 1;
328 p++;
329 num_arrays = *p;
330 p++;
331
332 printf("array cnt:%d nal_size:%d\n", num_arrays, *nal_size);
333 // Decode nal units from hvcC
334 for (i = 0; i < num_arrays; i++) {
335 uint8_t nal_type;
336 uint16_t numNalus;
337 int j;
338
339 nal_type = *p & 0x3F;
340 p++;
341 numNalus = WORD_BE(p);
342 p += 2;
343 for (j = 0; j < numNalus; j++) {
344 uint16_t nalsize = WORD_BE(p);
345 p += 2;
346 //printf("%d: len:%u\n", j, nalsize);
347 if (nal_type == HEVC_NAL_VPS || nal_type == HEVC_NAL_SPS ||
348 nal_type == HEVC_NAL_PPS) {
349 //NAL header
350 if (*nal_size == 3) {
351 memcpy(*o_data + cur_size, s_nal_3, 3);
352 cur_size += 3;
353 } else if (*nal_size == 4) {
354 memcpy(*o_data + cur_size, s_nal_4, 4);
355 cur_size += 4;
356 } else {
357 printf("invalid nal size:%d\n", *nal_size);
358 goto err_exit;
359 }
360
361 memcpy(*o_data + cur_size, p, nalsize);
362 cur_size += nalsize;
363 }
364 p += nalsize;
365 }
366 }
367 printf("header parse done. cur_size:%d\n", cur_size);
368 *o_size = cur_size;
369 return 0;
370err_exit:
371 free(*o_data);
372 dump("cur.dat", data, size);
373 return -2;
374}
375
376static void* dmx_thread_func (void *arg) {
377 AVPacket pkt;
378
379 /* initialize packet, set data to NULL, let the demuxer fill it */
380 av_init_packet(&pkt);
381 pkt.data = NULL;
382 pkt.size = 0;
383
384 /* read frames from the file */
385 while (av_read_frame(fmt_ctx, &pkt) >= 0) {
386 if (thread_quit)
387 break;
388 demux_packet(&pkt);
389 av_packet_unref(&pkt);
390 }
391
392 if (!thread_quit)
393 dec_cb->eos();
394
395 printf("dmx done, total vframe:%d\n", video_frame_count);
396 return NULL;
397}
398
399static void log_callback(void *ptr, int level,
400 const char *fmt, va_list vargs)
401{
Song Zhao9be28a32020-06-18 22:02:59 -0700402 if (log_level & 0x1)
Song Zhao1b237602020-02-13 10:58:57 -0800403 vprintf(fmt, vargs);
404}
405
406int demux_init(const char *file, struct dmx_cb *cb)
407{
408 int ret = 0;
409 AVCodecParameters *dec_ctx = NULL;
410
411 if (!file || !cb) {
412 printf("null pointer\n");
413 return 1;
414 }
415
416 dec_cb = cb;
417
418 av_log_set_level(AV_LOG_ERROR);
419 //av_log_set_level(AV_LOG_DEBUG);
420 av_log_set_callback(log_callback);
421
422 fmt_ctx = avformat_alloc_context();
423 /* open input file, and allocate format context */
424 ret = avformat_open_input(&fmt_ctx, file, NULL, NULL);
425 if (ret) {
426 printf("Could not open source file %s ret:%d %s\n", file, ret, av_err2str(ret));
427 return 2;
428 }
429
430 /* retrieve stream information */
431 if (avformat_find_stream_info(fmt_ctx, NULL) < 0) {
432 printf("Could not find stream information\n");
433 ret = 3;
434 goto end;
435 }
436
437 if (open_codec_context(&video_stream_idx, fmt_ctx, AVMEDIA_TYPE_VIDEO) >= 0) {
438 uint8_t *header;
439 int h_size;
440
441 video_stream = fmt_ctx->streams[video_stream_idx];
442 dec_ctx = video_stream->codecpar;
443
444 /* allocate image where the decoded image will be put */
445 v_data.width = dec_ctx->width;
446 v_data.height = dec_ctx->height;
447 if (dec_ctx->codec_id == AV_CODEC_ID_H264)
448 v_data.type = VIDEO_TYPE_H264;
449 else if (dec_ctx->codec_id == AV_CODEC_ID_H265)
450 v_data.type = VIDEO_TYPE_H265;
451 else if (dec_ctx->codec_id == AV_CODEC_ID_MPEG2VIDEO)
452 v_data.type = VIDEO_TYPE_MPEG2;
453 else if (dec_ctx->codec_id == AV_CODEC_ID_VP9)
454 v_data.type = VIDEO_TYPE_VP9;
455 else if (dec_ctx->codec_id == AV_CODEC_ID_AV1)
456 v_data.type = VIDEO_TYPE_AV1;
457 else {
458 printf("format not supported %d\n", dec_ctx->codec_id);
459 ret = 3;
460 goto end;
461 }
462
463
464 //printf("AV_CODEC_ID_H264:%d AV_CODEC_ID_H265:%d\n", AV_CODEC_ID_H264, AV_CODEC_ID_H265);
Song Zhaof781ce52020-06-10 23:44:16 -0700465 printf("video stream: format:%d %dx%d tu:%d/%d\n ",
466 dec_ctx->codec_id, v_data.width, v_data.height,
467 video_stream->time_base.num, video_stream->time_base.den);
Song Zhao1b237602020-02-13 10:58:57 -0800468
469 dec_cb->meta_done(&v_data);
470
471 printf("video header:%d\n", dec_ctx->extradata_size);
472 h_size = dec_ctx->extradata_size;
473 if (dec_ctx->codec_id == AV_CODEC_ID_H264 &&
474 dec_ctx->extradata_size) {
475 if(h264_header_parse(dec_ctx->extradata,
476 dec_ctx->extradata_size,
477 &header, &h_size, &nal_size)) {
478 printf("parse header fail\n");
479 ret = 5;
480 goto end;
481 }
482 dec_cb->write(header, h_size);
483 free(header);
484 } else if (dec_ctx->codec_id == AV_CODEC_ID_H265 &&
485 dec_ctx->extradata_size) {
486 if(h265_header_parse(dec_ctx->extradata,
487 dec_ctx->extradata_size,
488 &header, &h_size, &nal_size)) {
489 printf("parse header fail\n");
490 ret = 6;
491 goto end;
492 }
493 if (h_size)
494 dec_cb->write(header, h_size);
495 free(header);
496 } else if (dec_ctx->extradata_size) {
497 dec_cb->write(dec_ctx->extradata, dec_ctx->extradata_size);
498 }
499 }
500
501 /* dump input information to stderr */
502 av_dump_format(fmt_ctx, 0, file, 0);
503
504 if (!video_stream) {
505 printf("Could not find audio or video stream in the input, aborting\n");
506 ret = 7;
507 goto end;
508 }
509
510 if (pthread_create(&dmx_t, NULL, dmx_thread_func, NULL)) {
511 printf("Could not create thread, aborting\n");
512 ret = 8;
513 goto end;
514 }
515
516 return 0;
517
518end:
519 avformat_close_input(&fmt_ctx);
520 return ret;
521}
522
523int dmx_destroy() {
524 thread_quit = true;
525 pthread_join(dmx_t, NULL);
526 avformat_close_input(&fmt_ctx);
527 if (fmt_ctx)
528 avformat_free_context(fmt_ctx);
529 return 0;
530}