Permalink
Browse files

Implement some of LibavDemuxer and Stream

LibavDemuxer now reads data from the DataSource and calls
avformat_find_stream_info to buid a list of Streams.
  • Loading branch information...
simonhorlick committed May 26, 2012
1 parent 4144565 commit f366c00f0f72beebeeaa3491c5c3566a0b85ea2b
Showing with 128 additions and 8 deletions.
  1. +2 −2 Makefile
  2. +84 −1 libav_demuxer.cc
  3. +29 −4 libav_demuxer.h
  4. +1 −1 libav_demuxer_unittest.cc
  5. +8 −0 stream.cc
  6. +4 −0 stream.h
View
@@ -14,13 +14,13 @@ libav_demuxer.o: libav_demuxer.cc libav_demuxer.h data_source.h stream.h
libav_demuxer_unittest.o: libav_demuxer_unittest.cc libav_demuxer.h
$(CXX) $(CXXFLAGS) -I$(GTEST_DIR)/include -c $< -o $@
-libav_demuxer_unittest: libav_demuxer_unittest.o file_source.o libav_demuxer.o gtest_main.a
+libav_demuxer_unittest: libav_demuxer_unittest.o stream.o file_source.o libav_demuxer.o gtest_main.a
$(CXX) $(CXXFLAGS) $^ -lavformat -lpthread -o $@
file_source.o: file_source.cc file_source.h data_source.h
$(CXX) $(CXXFLAGS) -c $< -o $@
-stream.o: stream.cc
+stream.o: stream.cc stream.h
$(CXX) $(CXXFLAGS) -c $< -o $@
View
@@ -1,4 +1,7 @@
#include "libav_demuxer.h"
+#include "stream.h"
+
+#include <iostream>
extern "C"
{
@@ -7,18 +10,98 @@ extern "C"
LibavDemuxer::LibavDemuxer() {
av_register_all();
+ format_context_ = avformat_alloc_context();
+ source_ = 0;
+ io_context_ = 0;
}
LibavDemuxer::~LibavDemuxer() {
+ av_free(io_context_);
+ avformat_free_context(format_context_);
+}
+namespace
+{
+ int ReadPacket(void* opaque, uint8_t* buffer, int size)
+ {
+ LibavDemuxer* demuxer = reinterpret_cast<LibavDemuxer*>(opaque);
+ return demuxer->Read(buffer, size);
+ }
}
bool LibavDemuxer::Initialise(DataSource* source) {
source_ = source;
// Create custom libav function that reads from source_.
+ std::clog << "demuxer: registering custom IO handler for libav\n";
+ const int buffersize = 4096;
+ io_buffer_ = (unsigned char *)av_malloc(buffersize +
+ FF_INPUT_BUFFER_PADDING_SIZE);
+ io_context_ = avio_alloc_context(io_buffer_, buffersize, 0, this,
+ &::ReadPacket, 0, 0);
+
+ if(!io_context_) {
+ std::cerr << "demuxer: avio_alloc_context failed\n";
+ return false;
+ }
+ format_context_->pb = io_context_;
+
+ std::clog << "demuxer: opening input source\n";
+ int result = avformat_open_input(&format_context_, "", NULL, NULL);
+ if(result < 0)
+ {
+ char errbuf[128];
+ const char *errbuf_ptr = errbuf;
+
+ if(av_strerror(result, errbuf, sizeof(errbuf)) < 0)
+ errbuf_ptr = strerror(AVUNERROR(result));
+
+ std::cerr << "ffmpeg: avformat_open_input failed ("
+ << errbuf_ptr << ")\n";
+ return false;
+ }
+
+ streams_ = FindStreams();
+
+ return true;
+}
+
+std::vector<Stream*> LibavDemuxer::FindStreams()
+{
+ std::vector<Stream*> streams;
+
+ //std::clog << "demuxer: find stream info\n";
+ if(avformat_find_stream_info(format_context_, 0) < 0)
+ {
+ std::cerr << "ffmpeg error: av_find_stream_info\n";
+ return streams;
+ }
+
+ streams.resize(format_context_->nb_streams);
+
+ for(unsigned int i = 0; i < format_context_->nb_streams; i++)
+ {
+ //std::clog << "demuxer: stream " << i << "\n";
+ AVCodecContext* codec_context = format_context_->streams[i]->codec;
+
+ if(codec_context->codec_type == AVMEDIA_TYPE_VIDEO ||
+ codec_context->codec_type == AVMEDIA_TYPE_AUDIO)
+ {
+ streams[i] = new Stream(this, format_context_->streams[i]);
+ }
+ }
+ return streams;
+}
+
+int LibavDemuxer::Read(uint8_t* buffer, int size) {
+ return source_->Read(buffer, size);
+}
+
+void LibavDemuxer::PostDemuxTask() {
+
+}
+void LibavDemuxer::Demux() {
- return false;
}
View
@@ -1,24 +1,49 @@
#ifndef LIBAV_DEMUXER_H
#define LIBAV_DEMUXER_H
-#include <map>
-#include "stream.h"
+#include <vector>
+#include <cstdint>
#include "data_source.h"
+extern "C"
+{
+ #include <libavformat/avformat.h>
+}
+
+class Stream;
+
+// A Stream will call PostDemuxTask on the Demuxer whenever it requires more
+// data. The Demuxer will then read packets and pass these to the correct
+// streams until every Stream no longer requires data.
+
class LibavDemuxer {
public:
LibavDemuxer();
~LibavDemuxer();
bool Initialise(DataSource* source);
- std::map<int, Stream*>& GetStreams() {
+ // This method is called by libav to retrieve data from the DataSource.
+ int Read(uint8_t* buffer, int size);
+
+ // Start a demux task that will run in a seperate thread to the callee.
+ void PostDemuxTask();
+
+ // The actual method that handles demuxing.
+ void Demux();
+
+ std::vector<Stream*>& GetStreams() {
return streams_;
}
private:
+ std::vector<Stream*> FindStreams();
+
DataSource* source_;
- std::map<int, Stream*> streams_;
+ AVFormatContext* format_context_;
+ AVIOContext* io_context_;
+ unsigned char* io_buffer_;
+ std::vector<Stream*> streams_;
};
#endif // LIBAV_DEMUXER_H
@@ -27,7 +27,7 @@ class LibavDemuxerTest : public testing::Test {
TEST_F(LibavDemuxerTest, InitialiseNoStreams) {
DoInitialise("test/nostreams.ts");
- std::map<int, Stream*>& streams = demuxer_->GetStreams();
+ std::vector<Stream*>& streams = demuxer_->GetStreams();
EXPECT_TRUE(streams.empty());
}
View
@@ -1,3 +1,11 @@
#include "stream.h"
+#include "libav_demuxer.h"
+extern "C" {
+ #include <libavformat/avformat.h>
+}
+
+Stream::Stream(LibavDemuxer* demuxer, AVStream* stream) {
+
+}
View
@@ -1,8 +1,12 @@
#ifndef STREAM_H
#define STREAM_H
+class LibavDemuxer;
+struct AVStream;
+
class Stream {
public:
+ Stream(LibavDemuxer* demuxer, AVStream* stream);
};

0 comments on commit f366c00

Please sign in to comment.