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
|
#include "mkv_vp8x_decoder.h"
#include "../nsmkv/Lacing.h"
#include "../nsmkv/Cluster.h"
#include <mmsystem.h>
int MKVDecoder::CreateVideoDecoder(const char *codec_id, const nsmkv::TrackEntryData *track_entry_data, const nsmkv::VideoData *video_data, ifc_mkvvideodecoder **decoder)
{
if (!strcmp(codec_id, "V_VP8"))
{
vpx_codec_ctx_t codec;
if (vpx_codec_dec_init(&codec, &vpx_codec_vp8_dx_algo, NULL, 0) == VPX_CODEC_OK)
{
MKVVP8 *vp8 = new MKVVP8(codec, video_data);
*decoder = vp8;
return CREATEDECODER_SUCCESS;
}
#if 0
nsmkv::LacingState lacing_state;
if (nsmkv::Lacing::GetState(nsmkv::BlockBinary::XIPH_LACING, (const uint8_t *)track_entry_data->codec_private, track_entry_data->codec_private_len, &lacing_state))
{
const uint8_t *frame;
size_t frame_len;
uint16_t frame_number=0;
while (nsmkv::Lacing::GetFrame(frame_number, (const uint8_t *)track_entry_data->codec_private, track_entry_data->codec_private_len, &frame, &frame_len, &lacing_state))
{
ogg_packet packet = {const_cast<uint8_t *>(frame), frame_len, (frame_number==0), 0, 0 /*-1?*/, theora->packet_number++};
int ret = th_decode_headerin(&theora->info, &theora->comment, &theora->setup, &packet);
if (ret < 0)
goto bail;
frame_number++;
}
theora->decoder = th_decode_alloc(&theora->info, theora->setup);
if (!theora->decoder)
goto bail;
*decoder = theora;
return CREATEDECODER_SUCCESS;
}
bail:
delete theora;
#endif
return CREATEDECODER_FAILURE;
}
else
{
return CREATEDECODER_NOT_MINE;
}
}
#define CBCLASS MKVDecoder
START_DISPATCH;
CB(CREATE_VIDEO_DECODER, CreateVideoDecoder)
END_DISPATCH;
#undef CBCLASS
MKVVP8::MKVVP8(vpx_codec_ctx_t decoder, const nsmkv::VideoData *video_data) : decoder(decoder), video_data(video_data)
{
flushing=false;
}
int MKVVP8::GetOutputProperties(int *x, int *y, int *color_format, double *aspect_ratio)
{
vpx_codec_stream_info_t stream_info;
stream_info.sz = sizeof(stream_info);
if (vpx_codec_get_stream_info(&decoder, &stream_info) == VPX_CODEC_OK)
{
*x = stream_info.w;
*y = stream_info.h;
*aspect_ratio=1.0;
*color_format = mmioFOURCC('Y','V','1','2');
return MKV_SUCCESS;
}
return MKV_FAILURE;
}
int MKVVP8::DecodeBlock(const void *inputBuffer, size_t inputBufferBytes, uint64_t timestamp)
{
frame_iterator = 0;
vpx_codec_decode(&decoder, (const uint8_t *)inputBuffer, (unsigned int)inputBufferBytes, 0, 0);
return MKV_SUCCESS;
}
void MKVVP8::Flush()
{
flushing=true;
}
int MKVVP8::GetPicture(void **data, void **decoder_data, uint64_t *timestamp)
{
if (flushing)
{
vpx_codec_stream_info_t stream_info;
stream_info.sz = sizeof(stream_info);
if (vpx_codec_get_stream_info(&decoder, &stream_info) == VPX_CODEC_OK)
{
if (!stream_info.is_kf)
return MKV_FAILURE;
flushing=false;
}
}
vpx_image_t *image = vpx_codec_get_frame(&decoder, &frame_iterator);
if (image)
{
planes.y.baseAddr = image->planes[0];
planes.y.rowBytes = image->stride[0];
planes.u.baseAddr = image->planes[1];
planes.u.rowBytes = image->stride[1];
planes.v.baseAddr = image->planes[2];
planes.v.rowBytes = image->stride[2];
*data = &planes;
*decoder_data = 0;
return MKV_SUCCESS;
}
return MKV_FAILURE;
}
void MKVVP8::FreePicture(void *data, void *decoder_data)
{
}
void MKVVP8::HurryUp(int state)
{
}
void MKVVP8::Close()
{
vpx_codec_destroy(&decoder);
delete this;
}
#define CBCLASS MKVVP8
START_DISPATCH;
CB(GET_OUTPUT_PROPERTIES, GetOutputProperties)
CB(DECODE_BLOCK, DecodeBlock)
VCB(FLUSH, Flush)
CB(GET_PICTURE, GetPicture)
VCB(FREE_PICTURE, FreePicture)
VCB(HURRY_UP, HurryUp)
VCB(CLOSE, Close)
END_DISPATCH;
#undef CBCLASS
|