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