Skip to content

Commit 2d9864a

Browse files
committed
Open codecs for each stream in file
1 parent 8a76bd9 commit 2d9864a

File tree

4 files changed

+130
-125
lines changed

4 files changed

+130
-125
lines changed

avprobe.go

+45
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ extern void _wrap_ReadResult_packet_set_avprobe_6c983079c4703ea1(uintptr_t arg1,
4646
extern uintptr_t _wrap_ReadResult_packet_get_avprobe_6c983079c4703ea1(uintptr_t arg1);
4747
extern uintptr_t _wrap_new_ReadResult_avprobe_6c983079c4703ea1(void);
4848
extern void _wrap_delete_ReadResult_avprobe_6c983079c4703ea1(uintptr_t arg1);
49+
extern uintptr_t _wrap_new_InputStream_avprobe_6c983079c4703ea1(uintptr_t arg1, uintptr_t arg2);
50+
extern void _wrap_delete_InputStream_avprobe_6c983079c4703ea1(uintptr_t arg1);
4951
extern uintptr_t _wrap_new_Prober_avprobe_6c983079c4703ea1(void);
5052
extern void _wrap_delete_Prober_avprobe_6c983079c4703ea1(uintptr_t arg1);
5153
extern _Bool _wrap_Prober_open_avprobe_6c983079c4703ea1(uintptr_t arg1, swig_type_1 arg2);
@@ -242,6 +244,33 @@ type ReadResult interface {
242244
GetPacket() (_swig_ret Packet)
243245
}
244246

247+
type SwigcptrInputStream uintptr
248+
249+
func (p SwigcptrInputStream) Swigcptr() uintptr {
250+
return (uintptr)(p)
251+
}
252+
253+
func (p SwigcptrInputStream) SwigIsInputStream() {
254+
}
255+
256+
func NewInputStream(arg1 AVStream, arg2 AVCodecContext) (_swig_ret InputStream) {
257+
var swig_r InputStream
258+
_swig_i_0 := arg1.Swigcptr()
259+
_swig_i_1 := arg2.Swigcptr()
260+
swig_r = (InputStream)(SwigcptrInputStream(C._wrap_new_InputStream_avprobe_6c983079c4703ea1(C.uintptr_t(_swig_i_0), C.uintptr_t(_swig_i_1))))
261+
return swig_r
262+
}
263+
264+
func DeleteInputStream(arg1 InputStream) {
265+
_swig_i_0 := arg1.Swigcptr()
266+
C._wrap_delete_InputStream_avprobe_6c983079c4703ea1(C.uintptr_t(_swig_i_0))
267+
}
268+
269+
type InputStream interface {
270+
Swigcptr() uintptr
271+
SwigIsInputStream()
272+
}
273+
245274
type SwigcptrProber uintptr
246275

247276
func (p SwigcptrProber) Swigcptr() uintptr {
@@ -304,3 +333,19 @@ func (p SwigcptrInt64_t) Swigcptr() uintptr {
304333
return uintptr(p)
305334
}
306335

336+
type SwigcptrAVCodecContext uintptr
337+
type AVCodecContext interface {
338+
Swigcptr() uintptr;
339+
}
340+
func (p SwigcptrAVCodecContext) Swigcptr() uintptr {
341+
return uintptr(p)
342+
}
343+
344+
type SwigcptrAVStream uintptr
345+
type AVStream interface {
346+
Swigcptr() uintptr;
347+
}
348+
func (p SwigcptrAVStream) Swigcptr() uintptr {
349+
return uintptr(p)
350+
}
351+

prober.cpp

+35-111
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,6 @@ static void logging(const char *fmt, ...)
2525
//------------------------------------------------------------------------------
2626
Prober::~Prober()
2727
{
28-
avformat_close_input(&mFormatCtx);
29-
avcodec_free_context(&mCodecCtx);
3028
}
3129

3230
//------------------------------------------------------------------------------
@@ -48,15 +46,11 @@ bool Prober::open(const char *path)
4846
std::cerr << "prober could not get stream info";
4947
return false;
5048
}
51-
av_dump_format(mFormatCtx, 0, path, 0); // [4]
5249

53-
if(!findStreams())
54-
{
55-
std::cerr << "prober could not find streams in input";
56-
return false;
57-
}
50+
// TODO:
51+
av_dump_format(mFormatCtx, 0, path, 0);
5852

59-
if(!openCodec())
53+
if(!openCodecs())
6054
{
6155
std::cerr << "prober could not open codecs on input";
6256
return false;
@@ -68,121 +62,51 @@ bool Prober::open(const char *path)
6862
//------------------------------------------------------------------------------
6963
//
7064
//------------------------------------------------------------------------------
71-
static int decode_packet2(
72-
const AVStream *stream,
73-
AVCodecContext *codecContext,
74-
AVPacket *pkt,
75-
AVFrame *frame)
65+
bool Prober::openCodecs()
7666
{
77-
// printf("stream_index %d\n", pkt->stream_index);
78-
// printf("pts %d\n", pkt->pts);
79-
// printf("dts %d\n", pkt->dts);
80-
//printf("dts_time", pkt->dts, &st->time_base);
81-
//printf("duration %d\n", pkt->duration);
82-
//printf("duration_time", pkt->duration, &st->time_base);
83-
//print_val("size", pkt->size, unit_byte_str);
84-
85-
auto ret = avcodec_send_packet(codecContext, pkt);
86-
if(ret < 0)
67+
for(unsigned i = 0; i < mFormatCtx->nb_streams; i++)
8768
{
88-
printf("Error sending packet for decoding.");
89-
return -1;
90-
}
69+
const auto stream = mFormatCtx->streams[i];
9170

92-
while(ret >= 0)
93-
{
94-
ret = avcodec_receive_frame(codecContext, frame);
95-
// printf("receive frame: %d %d\n", frame->width, frame->height);
96-
if(ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
71+
logging("AVStream->time_base before open coded %d/%d", stream->time_base.num, stream->time_base.den);
72+
logging("AVStream->r_frame_rate before open coded %d/%d", stream->r_frame_rate.num, stream->r_frame_rate.den);
73+
74+
if(stream->codecpar->codec_id == AV_CODEC_ID_PROBE)
9775
{
98-
break;
76+
std::cerr << "Failed to probe codec for input stream " << stream->index << std::endl;
77+
mStreams.emplace_back(std::make_shared<InputStream>(nullptr, nullptr));
78+
continue;
9979
}
100-
else if(ret < 0)
80+
81+
auto codec = avcodec_find_decoder(stream->codecpar->codec_id);
82+
if(!codec)
10183
{
102-
printf("Error while decoding packet.");
103-
return -1;
84+
std::cerr
85+
<< "Unsupported codec with id " << stream->codecpar->codec_id
86+
<< " for input stream " << stream->index << std::endl;
87+
return false;
10488
}
10589

106-
logging(
107-
"Frame %d (type=%c, size=%d bytes, format=%d) pts %d key_frame %d [DTS %d]",
108-
codecContext->frame_number,
109-
av_get_picture_type_char(frame->pict_type),
110-
frame->pkt_size,
111-
frame->format,
112-
frame->pts,
113-
frame->key_frame,
114-
frame->coded_picture_number);
115-
}
116-
117-
return 0;
118-
}
119-
120-
//------------------------------------------------------------------------------
121-
//
122-
//------------------------------------------------------------------------------
123-
bool Prober::findStreams()
124-
{
125-
for(unsigned i = 0; i < mFormatCtx->nb_streams; i++)
126-
{
127-
auto codecParam = mFormatCtx->streams[i]->codecpar;
128-
logging("AVStream->time_base before open coded %d/%d", mFormatCtx->streams[i]->time_base.num, mFormatCtx->streams[i]->time_base.den);
129-
logging("AVStream->r_frame_rate before open coded %d/%d", mFormatCtx->streams[i]->r_frame_rate.num, mFormatCtx->streams[i]->r_frame_rate.den);
130-
131-
if(codecParam->codec_type == AVMEDIA_TYPE_VIDEO)
132-
{
133-
mVideoStream = i;
134-
mCodecParameters = mFormatCtx->streams[mVideoStream]->codecpar;
135-
}
136-
else if(codecParam->codec_type == AVMEDIA_TYPE_AUDIO)
90+
auto codecCtx = avcodec_alloc_context3(codec);
91+
if(!codecCtx)
13792
{
138-
logging("Audio Codec: %d channels, sample rate %d", codecParam->channels, codecParam->sample_rate);
139-
mAudioStream = i;
140-
mAudioCodecParameters = mFormatCtx->streams[mAudioStream]->codecpar;
93+
std::cerr << "could not allocate memory for Codec Context";
94+
return false;
14195
}
142-
}
143-
144-
return mAudioStream != -1 || mVideoStream != -1;
145-
}
14696

147-
//------------------------------------------------------------------------------
148-
//
149-
//------------------------------------------------------------------------------
150-
bool Prober::openCodec()
151-
{
152-
auto codec = avcodec_find_decoder(mCodecParameters->codec_id);
153-
if(!codec)
154-
{
155-
std::cerr << "unsupported codec";
156-
return false;
157-
}
158-
159-
/**
160-
* Note that we must not use the AVCodecContext from the video stream
161-
* directly! So we have to use avcodec_copy_context() to copy the
162-
* context to a new location (after allocating memory for it, of
163-
* course).
164-
*/
165-
166-
// Copy context
167-
mCodecCtx = avcodec_alloc_context3(codec);
168-
if(!mCodecCtx)
169-
{
170-
std::cerr << "could not allocate memory for Codec Context";
171-
return false;
172-
}
97+
if(avcodec_parameters_to_context(codecCtx, stream->codecpar) < 0)
98+
{
99+
printf("Could not copy codec context.\n");
100+
return false;
101+
}
173102

174-
auto ret = avcodec_parameters_to_context(mCodecCtx, mCodecParameters);
175-
if(ret != 0)
176-
{
177-
printf("Could not copy codec context.\n");
178-
return false;
179-
}
103+
if(avcodec_open2(codecCtx, codec, nullptr) < 0)
104+
{
105+
std::cerr << "Failed to open codec";
106+
return false;
107+
}
180108

181-
// Open codec
182-
if(avcodec_open2(mCodecCtx, codec, nullptr) < 0)
183-
{
184-
std::cerr << "Failed to open Codec";
185-
return false;
109+
mStreams.emplace_back(std::make_shared<InputStream>(stream, codecCtx));
186110
}
187111

188112
return true;

prober.h

+21-14
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22

33
#include <string>
44
#include <cstdint>
5-
#include <tuple>
5+
#include <vector>
6+
#include <memory>
67

78
extern "C"
89
{
@@ -20,6 +21,23 @@ struct ReadResult
2021
Packet *packet;
2122
};
2223

24+
class InputStream {
25+
public:
26+
InputStream(const AVStream *stream, AVCodecContext *codecCtx)
27+
: mStream(stream), mCodecCtx(codecCtx)
28+
{
29+
}
30+
31+
~InputStream()
32+
{
33+
avcodec_free_context(&this->mCodecCtx);
34+
}
35+
36+
private:
37+
const AVStream *mStream;
38+
AVCodecContext *mCodecCtx;
39+
};
40+
2341
class Prober
2442
{
2543
public:
@@ -30,23 +48,12 @@ class Prober
3048
ReadResult readNextPacket();
3149

3250
private:
33-
bool findStreams();
34-
bool openCodec();
51+
bool openCodecs();
3552

3653
std::string mUrl;
3754

38-
int mVideoStream {-1};
39-
int mAudioStream {-1};
40-
4155
AVFormatContext *mFormatCtx{nullptr};
4256

43-
AVCodecParameters *mCodecParameters{nullptr};
44-
AVCodecParameters *mAudioCodecParameters{nullptr};
45-
46-
AVCodecContext *mCodecCtx{nullptr};
47-
// AVCodecContext *mAudioCodecCtx{nullptr};
48-
49-
AVCodec *mCodec{nullptr};
50-
AVCodec *mAudioCodec{nullptr};
57+
std::vector<std::shared_ptr<InputStream>> mStreams;
5158
};
5259
}

test/CMakeLists.txt

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
cmake_minimum_required(VERSION 3.17)
2+
3+
project(prober)
4+
5+
find_package(PkgConfig REQUIRED)
6+
pkg_check_modules(LIBAV REQUIRED IMPORTED_TARGET
7+
libavformat
8+
libavcodec
9+
)
10+
11+
add_executable(${PROJECT_NAME}
12+
main.cpp
13+
../ffpacket.cpp
14+
../prober.cpp
15+
)
16+
17+
target_include_directories(${PROJECT_NAME} PRIVATE
18+
${CMAKE_CURRENT_SOURCE_DIR}/..
19+
)
20+
21+
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -s")
22+
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -s")
23+
24+
target_compile_options(${PROJECT_NAME} PRIVATE
25+
-std=c++17 -Wall -fpermissive -Wno-deprecated-declarations)
26+
27+
target_link_libraries(${PROJECT_NAME} PUBLIC
28+
PkgConfig::LIBAV
29+
)

0 commit comments

Comments
 (0)