-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathdemuxer.c
169 lines (148 loc) · 6.84 KB
/
demuxer.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
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
#include "ngtc.h"
#include "lav.h"
#include "demuxer.h"
int setupDemuxerFormat(DemuxerSettings *ds, char *file, struct hqv_data *hqv) {
AVProbeData probe_data, *pd = &probe_data;
ds->pFormatCtx = avformat_alloc_context();
ds->pFormatCtx->flags |= AVFMT_FLAG_NONBLOCK;
ds->pFormatCtx->flags |= AVFMT_FLAG_GENPTS;
#ifdef AVFMT_FLAG_IGNDTS
ds->pFormatCtx->flags |= AVFMT_FLAG_IGNDTS;
#endif
if (ds->streaming)
ds->pFormatCtx->flags |= AVFMT_NOFILE|AVFMT_FLAG_IGNIDX;
// Setup input format for raw A/V
if (ds->input_format != NULL) {
ds->fmt = av_iformat_next(NULL);
if (ds->fmt != NULL && ds->fmt->name != NULL && strcmp(ds->fmt->name, ds->input_format) != 0) {
do {
ds->fmt = av_iformat_next(ds->fmt);
if (ds->fmt == NULL || ds->fmt->name == NULL)
break;
} while (strcmp(ds->fmt->name, ds->input_format) != 0);
}
if (ds->fmt)
av_log(NULL, AV_LOG_INFO, "Input format: %s\n", ds->fmt->long_name);
else
av_log(NULL, AV_LOG_WARNING, "Failed finding input format: %s\n", ds->input_format);
}
if (ds->streaming)
ds->stream_buffer = (uint8_t*)av_malloc(STREAM_BUFFER_SIZE);
// Try to figure out input format
if (ds->streaming && ds->fmt == NULL) {
pd->filename = "";
if (file)
pd->filename = file;
pd->buf = ds->stream_buffer;
pd->buf_size = STREAM_BUFFER_SIZE;
// Wait till have enough input data
while(av_fifo_size(hqv->fifo) < STREAM_BUFFER_SIZE && continueDecoding)
usleep(33000);
if (!continueDecoding)
exit(0);
// Copy some fifo data
memcpy(ds->stream_buffer, hqv->fifo->buffer, STREAM_BUFFER_SIZE);
// Probe input format
ds->fmt = av_probe_input_format(pd, 1);
if (!ds->fmt) {
av_log(NULL, AV_LOG_FATAL, "Failed probing input file: %s\n", file);
exit(1);
} else
av_log(NULL, AV_LOG_INFO, "Input format: %s\n", ds->fmt->long_name);
}
// Open Input File
if (ds->streaming) {
// Streaming input
ds->pb = av_alloc_put_byte(ds->stream_buffer, STREAM_BUFFER_SIZE, 0,
hqv, fifo_read, NULL, NULL);
ds->pb->is_streamed = 1;
// Open video device stream
if (av_open_input_stream(&ds->pFormatCtx, ds->pb, file, ds->fmt, ds->ap) != 0) {
av_log(NULL, AV_LOG_FATAL, "%s: could not open device stream\n", file);
return -1; // Couldn't open file
}
} else {
// Open file
if (av_open_input_file(&ds->pFormatCtx, file, ds->fmt, 0, ds->ap) != 0) {
av_log(NULL, AV_LOG_FATAL, "%s: could not openfile\n", file);
return -1; // Couldn't open file
}
}
// Retrieve stream information
if (av_find_stream_info(ds->pFormatCtx) < 0) {
av_log(NULL, AV_LOG_FATAL, "%s: could not find codec parameters\n", file);
return -1;
}
return 0;
}
int setupDemuxerCodecs(DemuxerSettings *ds) {
AVCodec *pCodecVideo, *pCodecAudio, *pCodecSub;
if (ds->do_video) {
ds->pCodecCtxVideo = ds->pFormatCtx->streams[ds->videoStream]->codec;
// Find the decoder for the video stream
pCodecVideo = avcodec_find_decoder(ds->pCodecCtxVideo->codec_id);
if (pCodecVideo == NULL) {
av_log(NULL, AV_LOG_FATAL,
"Error: Codec [%d] for video not found.\n", ds->pCodecCtxVideo->codec_id);
return -1; // Codec not found
}
// Open video codec
if (avcodec_open(ds->pCodecCtxVideo, pCodecVideo) < 0) {
av_log(NULL, AV_LOG_FATAL,
"Error: Codec for video not able to open.\n");
return -1; // Could not open codec
}
// Hack to correct wrong frame rates that seem to be generated by some codecs
if (ds->pCodecCtxVideo->time_base.num > 1000
&& ds->pCodecCtxVideo->time_base.den == 1)
ds->pCodecCtxVideo->time_base.den = 1000;
}
if (ds->do_audio) {
ds->pCodecCtxAudio = ds->pFormatCtx->streams[ds->audioStream]->codec;
// Find the decoder for the audio stream
pCodecAudio = avcodec_find_decoder(ds->pCodecCtxAudio->codec_id);
if (pCodecAudio == NULL) {
av_log(NULL, AV_LOG_FATAL,
"Error: Codec [%d] for audio not found.\n", ds->pCodecCtxAudio->codec_id);
return -1; // Codec not found
}
// Open audio codec
if (avcodec_open(ds->pCodecCtxAudio, pCodecAudio) < 0) {
av_log(NULL, AV_LOG_FATAL,
"Error: Codec for audio not able to open.\n");
return -1; // Could not open codec
}
}
if (ds->do_sub) {
ds->pCodecCtxSub = ds->pFormatCtx->streams[ds->subStream]->codec;
// Find the decoder for the subtitle stream
pCodecSub = avcodec_find_decoder(ds->pCodecCtxSub->codec_id);
if (pCodecSub == NULL) {
av_log(NULL, AV_LOG_FATAL,
"Error: Codec [%d] for subtitle not found.\n", ds->pCodecCtxSub->codec_id);
//return -1; // Codec not found
ds->pCodecCtxSub = NULL;
}
// Open subtitle codec
if (ds->pCodecCtxSub && avcodec_open(ds->pCodecCtxSub, pCodecSub) < 0) {
av_log(NULL, AV_LOG_FATAL,
"Error: Codec for subtitle not able to open.\n");
return -1; // Could not open codec
}
}
return 0;
}
void freeDemuxer(DemuxerSettings *ds) {
if (ds->do_video && ds->pCodecCtxVideo)
avcodec_close(ds->pCodecCtxVideo);
if (ds->do_audio && ds->pCodecCtxAudio)
avcodec_close(ds->pCodecCtxAudio);
if (ds->do_sub && ds->pCodecCtxSub)
avcodec_close(ds->pCodecCtxSub);
if (ds->streaming) {
av_free(ds->stream_buffer);
av_close_input_stream(ds->pFormatCtx);
av_freep(&ds->pb);
} else
av_close_input_file(ds->pFormatCtx);
}