/src/ffmpeg/libavcodec/tak_parser.c
Line | Count | Source |
1 | | /* |
2 | | * TAK parser |
3 | | * Copyright (c) 2012 Michael Niedermayer |
4 | | * |
5 | | * This file is part of FFmpeg. |
6 | | * |
7 | | * FFmpeg is free software; you can redistribute it and/or |
8 | | * modify it under the terms of the GNU Lesser General Public |
9 | | * License as published by the Free Software Foundation; either |
10 | | * version 2.1 of the License, or (at your option) any later version. |
11 | | * |
12 | | * FFmpeg is distributed in the hope that it will be useful, |
13 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
15 | | * Lesser General Public License for more details. |
16 | | * |
17 | | * You should have received a copy of the GNU Lesser General Public |
18 | | * License along with FFmpeg; if not, write to the Free Software |
19 | | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
20 | | */ |
21 | | |
22 | | /** |
23 | | * @file |
24 | | * TAK parser |
25 | | **/ |
26 | | |
27 | | #define CACHED_BITSTREAM_READER !ARCH_X86_32 |
28 | | #define BITSTREAM_READER_LE |
29 | | #include "parser.h" |
30 | | #include "parser_internal.h" |
31 | | #include "tak.h" |
32 | | |
33 | | typedef struct TAKParseContext { |
34 | | ParseContext pc; |
35 | | TAKStreamInfo ti; |
36 | | int index; |
37 | | } TAKParseContext; |
38 | | |
39 | | static int tak_parse(AVCodecParserContext *s, AVCodecContext *avctx, |
40 | | const uint8_t **poutbuf, int *poutbuf_size, |
41 | | const uint8_t *buf, int buf_size) |
42 | 2.84M | { |
43 | 2.84M | TAKParseContext *t = s->priv_data; |
44 | 2.84M | ParseContext *pc = &t->pc; |
45 | 2.84M | int next = END_NOT_FOUND; |
46 | 2.84M | GetBitContext gb; |
47 | 2.84M | int consumed = 0; |
48 | 2.84M | int needed = buf_size ? TAK_MAX_FRAME_HEADER_BYTES : 8; |
49 | 2.84M | int ret; |
50 | | |
51 | 2.84M | *poutbuf = buf; |
52 | 2.84M | *poutbuf_size = buf_size; |
53 | | |
54 | 2.84M | if (s->flags & PARSER_FLAG_COMPLETE_FRAMES) { |
55 | 0 | TAKStreamInfo ti; |
56 | 0 | if ((ret = init_get_bits8(&gb, buf, buf_size)) < 0) |
57 | 0 | return buf_size; |
58 | 0 | if (!ff_tak_decode_frame_header(avctx, &gb, &ti, 127)) |
59 | 0 | s->duration = t->ti.last_frame_samples ? t->ti.last_frame_samples |
60 | 0 | : t->ti.frame_samples; |
61 | 0 | return buf_size; |
62 | 0 | } |
63 | | |
64 | 6.76M | while (buf_size || t->index + needed <= pc->index) { |
65 | 5.60M | if (buf_size && t->index + TAK_MAX_FRAME_HEADER_BYTES > pc->index) { |
66 | 5.60M | int tmp_buf_size = FFMIN(TAK_MAX_FRAME_HEADER_BYTES, |
67 | 5.60M | buf_size); |
68 | 5.60M | const uint8_t *tmp_buf = buf; |
69 | | |
70 | 5.60M | if (ff_combine_frame(pc, END_NOT_FOUND, &tmp_buf, &tmp_buf_size) != -1) |
71 | 0 | goto fail; |
72 | 5.60M | consumed += tmp_buf_size; |
73 | 5.60M | buf += tmp_buf_size; |
74 | 5.60M | buf_size -= tmp_buf_size; |
75 | 5.60M | } |
76 | | |
77 | 89.5M | for (; t->index + needed <= pc->index; t->index++) { |
78 | 85.6M | if (pc->buffer[ t->index ] == 0xFF && |
79 | 6.94M | pc->buffer[ t->index + 1 ] == 0xA0) { |
80 | 3.47M | TAKStreamInfo ti; |
81 | | |
82 | 3.47M | if ((ret = init_get_bits8(&gb, pc->buffer + t->index, |
83 | 3.47M | pc->index - t->index)) < 0) |
84 | 0 | goto fail; |
85 | 3.47M | if (!ff_tak_decode_frame_header(avctx, &gb, |
86 | 3.47M | pc->frame_start_found ? &ti : &t->ti, 127) && |
87 | 3.44M | !ff_tak_check_crc(pc->buffer + t->index, |
88 | 3.44M | get_bits_count(&gb) / 8)) { |
89 | 3.36M | if (!pc->frame_start_found) { |
90 | 1.68M | pc->frame_start_found = 1; |
91 | 1.68M | s->duration = t->ti.last_frame_samples ? |
92 | 4.18k | t->ti.last_frame_samples : |
93 | 1.68M | t->ti.frame_samples; |
94 | 1.68M | s->key_frame = !!(t->ti.flags & TAK_FRAME_FLAG_HAS_INFO); |
95 | 1.68M | } else { |
96 | 1.68M | pc->frame_start_found = 0; |
97 | 1.68M | next = t->index - pc->index; |
98 | 1.68M | t->index = 0; |
99 | 1.68M | goto found; |
100 | 1.68M | } |
101 | 3.36M | } |
102 | 3.47M | } |
103 | 85.6M | } |
104 | 5.60M | } |
105 | 2.84M | found: |
106 | | |
107 | 2.84M | if (consumed && !buf_size && next == END_NOT_FOUND || |
108 | 1.68M | ff_combine_frame(pc, next, &buf, &buf_size) < 0) { |
109 | 1.15M | goto fail; |
110 | 1.15M | } |
111 | | |
112 | 1.68M | if (next != END_NOT_FOUND) { |
113 | 1.68M | next += consumed; |
114 | 1.68M | pc->overread = FFMAX(0, -next); |
115 | 1.68M | } |
116 | | |
117 | 1.68M | *poutbuf = buf; |
118 | 1.68M | *poutbuf_size = buf_size; |
119 | 1.68M | return next; |
120 | | |
121 | 1.15M | fail: |
122 | | *poutbuf = NULL; |
123 | 1.15M | *poutbuf_size = 0; |
124 | 1.15M | return buf_size + consumed; |
125 | 2.84M | } |
126 | | |
127 | | const FFCodecParser ff_tak_parser = { |
128 | | PARSER_CODEC_LIST(AV_CODEC_ID_TAK), |
129 | | .priv_data_size = sizeof(TAKParseContext), |
130 | | .parse = tak_parse, |
131 | | .close = ff_parse_close, |
132 | | }; |