-
Notifications
You must be signed in to change notification settings - Fork 1
/
es.cpp
162 lines (134 loc) · 4.51 KB
/
es.cpp
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
155
156
157
158
159
160
161
162
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <sys/mman.h>
#include <typeinfo>
#include "es.hpp"
#include "mpegheader.hpp"
#include "exceptions.hpp"
#include "bitreader.hpp"
#include "framebuffer.hpp"
#include "picture.hpp"
const uint pool_slots = 50;
ES::ES( File *s_file, void (*progress)( off_t size, off_t location ) )
{
file = s_file;
first_header = last_header = NULL;
/* Find first sequence header */
/* We can't decode pictures before this, in general,
because we don't know the quantization matrices. */
off_t start = startfinder( 0, progress, &ES::first_sequence );
if ( start == -1 ) {
throw SequenceNotFound();
}
/* Ingest every start code, including before "start" */
seq = NULL;
startfinder( 0, progress, &ES::add_header );
if ( !seq ) {
throw SequenceNotFound();
}
/* Make ghost sequence header at start */
MPEGHeader *real_first_header = first_header;
Sequence *ghost_sequence = new Sequence( *seq );
SequenceExtension *first_extension = dynamic_cast<SequenceExtension *>( seq->get_next() );
SequenceExtension *ghost_extension = new SequenceExtension( *first_extension );
if ( (ghost_sequence == NULL) || (first_extension == NULL) || (ghost_extension == NULL) ) {
fprintf( stderr, "Problem assembling ghost sequence or extension header.\n" );
throw MPEGInvalid();
}
first_header = ghost_sequence;
ghost_sequence->override_next( ghost_extension );
ghost_extension->override_next( real_first_header );
ghost_sequence->set_unknown_quantiser_flags();
/* Link headers to one another as appropriate */
for ( MPEGHeader *hdr = first_header; hdr != NULL; hdr = hdr->get_next() ) {
hdr->link();
}
pool = new BufferPool( pool_slots, seq->get_mb_width(),
seq->get_mb_height() );
/* Figure out the display order of each picture and link each
from the coded_picture and displayed_picture arrays */
number_pictures();
/* Count up duration in seconds */
duration_numer = 0;
duration_denom = 2 * seq->get_frame_rate_numerator();
uint ticks = seq->get_frame_rate_denominator();
for ( uint i = 0; i < get_num_pictures(); i++ ) {
displayed_picture[ i ]->set_time( duration_numer / (double)duration_denom );
duration_numer += ticks * displayed_picture[ i ]->num_fields();
}
duration = duration_numer / (double)duration_denom;
}
ES::~ES()
{
MPEGHeader *hdr = first_header;
while ( hdr != NULL ) {
MPEGHeader *next = hdr->get_next();
delete hdr;
hdr = next;
}
delete pool;
delete[] coded_picture;
delete[] displayed_picture;
}
void ES::number_pictures( void )
{
/* Number each picture */
Picture *oanchor = NULL;
Picture *nanchor = NULL;
uint coded_order = 0;
uint display_order = 0;
for ( MPEGHeader *hdr = first_header; hdr != NULL; hdr = hdr->get_next() ) {
if ( typeid( *hdr ) == typeid( Picture ) ) {
Picture *tp = static_cast<Picture *>( hdr );
tp->set_coded( coded_order++ );
switch ( tp->get_type() ) {
case B:
tp->set_display( display_order++ );
tp->set_forward( oanchor );
tp->set_backward( nanchor );
if ( (oanchor == NULL) || (nanchor == NULL)
|| (oanchor->problem()) || (nanchor->problem()) ) tp->set_broken( true );
break;
case P:
tp->set_forward( nanchor );
if ( (nanchor == NULL) || nanchor->problem() ) tp->set_broken( true );
/* don't break */
case I:
if ( nanchor ) nanchor->set_display( display_order++ );
oanchor = nanchor;
nanchor = tp;
break;
}
} else if ( typeid( *hdr ) == typeid( SequenceEnd ) ) {
if ( nanchor ) nanchor->set_display( display_order++ );
nanchor = NULL;
}
}
if ( nanchor && (nanchor->get_display() == -1) ) {
nanchor->set_display( display_order++ );
nanchor->set_unclean( true );
nanchor = NULL;
}
ahabassert( coded_order == display_order );
num_pictures = coded_order;
/* Allocate memory */
coded_picture = new Picture *[ num_pictures ];
displayed_picture = new Picture *[ num_pictures ];
/* Make pointers in order */
for ( MPEGHeader *hdr = first_header; hdr != NULL; hdr = hdr->get_next() ) {
if ( typeid( *hdr ) == typeid( Picture ) ) {
Picture *tp = static_cast<Picture *>( hdr );
uint this_coded = tp->get_coded();
uint this_display = tp->get_display();
tp->init_fh( pool );
ahabassert( this_coded < num_pictures );
ahabassert( this_coded < num_pictures );
coded_picture[ this_coded ] = tp;
displayed_picture[ this_display ] = tp;
}
}
}