forked from gfto/libtsfuncs
-
Notifications
You must be signed in to change notification settings - Fork 0
/
pes_data.c
154 lines (135 loc) · 4.38 KB
/
pes_data.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
/*
* Working with PES entries
* Copyright (C) 2010-2011 Unix Solutions Ltd.
*
* Released under MIT license.
* See LICENSE-MIT.txt for license terms.
*/
#include <stdlib.h>
#include <string.h>
#include "tsdata.h"
#include "tsfuncs.h"
#define START_ENTRIES 1
#define ENTRIES_INCREMENT 1
static struct pes_entry *pes_entry_alloc(uint16_t pid) {
//ts_LOGf("Alloc pes_entry pid = %03x\n", pid);
struct pes_entry *e = malloc(sizeof(struct pes_entry));
e->pid = pid;
e->pes = ts_pes_alloc();
e->pes_next = NULL;
return e;
}
static void pes_entry_free(struct pes_entry **pentry) {
struct pes_entry *entry = *pentry;
if (entry) {
ts_pes_free(&entry->pes);
ts_pes_free(&entry->pes_next);
FREE(*pentry);
}
}
static struct pes_entry *pes_entry_find(struct pes_array *pa, uint16_t pid) {
int i;
for (i=0;i<pa->max;i++) {
struct pes_entry *e = pa->entries[i];
if (e && e->pid == pid) {
return e;
}
}
return NULL;
}
struct pes_array *pes_array_alloc() {
struct pes_array *pa = calloc(1, sizeof(struct pes_array));
pa->max = START_ENTRIES;
pa->entries = calloc(sizeof(struct pes_entry *), pa->max);
return pa;
}
struct pes_array *pes_array_realloc(struct pes_array *pa) {
pa->max += ENTRIES_INCREMENT;
pa->entries = realloc(pa->entries, sizeof(struct pes_entry *) * pa->max);
memset(&pa->entries[pa->cur], 0, sizeof(struct pes_entry *) * ((pa->max-1) - pa->cur));
return pa;
}
void pes_array_dump(struct pes_array *pa) {
int i;
ts_LOGf("pa->max=%d\n", pa->max);
ts_LOGf("pa->cur=%d\n", pa->cur);
for (i=0;i<pa->max;i++) {
ts_LOGf("pa->entry[%d]=0x%p\n", i, pa->entries[i]);
if (pa->entries[i]) {
ts_LOGf("pa->entry[%d]->pid=%03x\n", i, pa->entries[i]->pid);
ts_LOGf("pa->entry[%d]->pes=%p\n", i, pa->entries[i]->pes);
ts_pes_dump(pa->entries[i]->pes);
}
}
}
void pes_array_free(struct pes_array **ppa) {
int i;
struct pes_array *pa = *ppa;
if (pa) {
for (i=0;i<pa->max;i++) {
pes_entry_free(&pa->entries[i]);
}
free(pa->entries);
FREE(*ppa);
}
}
struct pes_entry *pes_array_push_packet(struct pes_array *pa, uint16_t pid, struct ts_pat *pat, struct ts_pmt *pmt, uint8_t *ts_packet) {
int i;
if (ts_is_psi_pid(pid, pat))
return NULL;
struct pes_entry *p = pes_entry_find(pa, pid); // Find existing entry
if (!p) { // New entry!
int pes_carrying_pid = 0; // check if PID is mentioned in PMT
for (i=0;i<pmt->streams_num;i++) {
struct ts_pmt_stream *stream = pmt->streams[i];
// Stream_type 0x80..0xff - user private
// Stream_type 0x05 - private sections
if (stream->pid == pid) {
switch (stream->stream_type) {
case 0x01: // return "11172-2 video (MPEG-1)";
case 0x02: // return "H.262/13818-2 video (MPEG-2) or 11172-2 constrained video";
case 0x03: // return "11172-3 audio (MPEG-1)";
case 0x04: // return "13818-3 audio (MPEG-2)";
case 0x06: // return "H.222.0/13818-1 PES private data";
case 0x07: // return "13522 MHEG";
case 0x08: // return "H.222.0/13818-1 Annex A - DSM CC";
case 0x09: // return "H.222.1";
case 0x0A: // return "13818-6 type A";
case 0x0B: // return "13818-6 type B";
case 0x0C: // return "13818-6 type C";
case 0x0D: // return "13818-6 type D";
case 0x0E: // return "H.222.0/13818-1 auxiliary";
case 0x0F: // return "13818-7 Audio with ADTS transport syntax";
case 0x10: // return "14496-2 Visual (MPEG-4 part 2 video)";
case 0x11: // return "14496-3 Audio with LATM transport syntax (14496-3/AMD 1)";
case 0x15: // return "Metadata in PES packets";
case 0x1B: // return "H.264/14496-10 video (MPEG-4/AVC)";
case 0x42: // return "AVS Video";
pes_carrying_pid = 1;
}
break;
}
}
if (!pes_carrying_pid) // We are not interrested
return NULL;
if (pa->cur >= pa->max) // Is there enough space in pes_array
pa = pes_array_realloc(pa); // Try to get some more
p = pes_entry_alloc(pid);
pa->entries[pa->cur++] = p;
}
// Last packet finished video PES and we saved it here
if (p->pes_next) {
ts_pes_free(&p->pes);
p->pes = p->pes_next;
p->pes_next = NULL;
}
// Video PES packets have unknown size, so we need to look one packet in the
// future to know when video PES is finished.
if (ts_pes_is_finished(p->pes, ts_packet)) {
p->pes_next = ts_pes_alloc();
p->pes_next = ts_pes_push_packet(p->pes_next, ts_packet, pmt, pid);
} else {
p->pes = ts_pes_push_packet(p->pes, ts_packet, pmt, pid);
}
return p;
}