Skip to content

Commit

Permalink
prototype 0
Browse files Browse the repository at this point in the history
  • Loading branch information
Alexandr Kutuzov committed Sep 17, 2012
1 parent 75d5617 commit a5a2a6b
Show file tree
Hide file tree
Showing 17 changed files with 381 additions and 59 deletions.
10 changes: 7 additions & 3 deletions application.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,23 +10,27 @@
Application::Application(int argc, char *argv[])
: QApplication(argc, argv), platform_support(0), main_window(0), player(0), playlist(0)
{
// Allocate
platform_support = new MacSupport();
main_window = new MainWindow();
player = new Player();
playlist = new PlayList();
player = new Player();

// Connect
main_window->setPlaylist(playlist);
player->setPlaylist(playlist);

// TODO: remove it
platform_support->setDockBadge("trolo");

platform_support->setCustomBorderColor(QColor(83,83,83));
platform_support->setCustomTitleColor(QColor(226,226,226));
platform_support->installCustomFrame();

platform_support->setDockOverlay(0);

// Connect signals
connect(platform_support, SIGNAL( dockClicked() ), main_window, SLOT( show() ));
connect(main_window, SIGNAL( droppedUrls(QList<QUrl>) ), playlist, SLOT( appendUrls(QList<QUrl>) ));
connect(main_window, SIGNAL( playPause() ), player, SLOT( playPause() ));
}

Application::~Application()
Expand Down
24 changes: 24 additions & 0 deletions avcondition.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#include "avcondition.h"

AVCondition::AVCondition() :
condition()
{
pthread_cond_init(&condition, NULL);
}

AVCondition::~AVCondition()
{
pthread_cond_destroy(&condition);
}

bool AVCondition::wait()
{
pthread_cond_wait(&condition, &mutex);
return true;
}

bool AVCondition::signal()
{
pthread_cond_signal(&condition);
return true;
}
19 changes: 19 additions & 0 deletions avcondition.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#ifndef AVCONDITION_H
#define AVCONDITION_H

#include "avmutex.h"

class AVCondition : public AVMutex
{
public:
explicit AVCondition();
virtual ~AVCondition();

bool wait();
bool signal();

protected:
pthread_cond_t condition;
};

#endif // AVCONDITION_H
99 changes: 76 additions & 23 deletions avfile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ extern "C" {
static volatile bool ffmpeginit = false;

AVFile::AVFile() :
formatCtx(0), codecCtx(0), swrCtx(0), audioStream(-1), ring(0)
formatCtx(0), codecCtx(0), swrCtx(0), audioStream(-1), ring(0), conditon()
{
qDebug() << "AVFile: created" << this;
if (!ffmpeginit) {
Expand All @@ -26,11 +26,14 @@ AVFile::AVFile() :
AVFile::~AVFile()
{
close();
join();
qDebug() << "AVFile: destroyed" << this;
}

void AVFile::open(const char *url)
{
qDebug() << "AVFile: trying to open" << url;

if (formatCtx)
throw AVException("Programming error: i already did it");

Expand All @@ -53,92 +56,142 @@ void AVFile::open(const char *url)
throw AVException("Could not open codec");

allocRing();
allocSWR();
}

void AVFile::runDecoder()
void AVFile::startDecoder()
{
int len = 0;
int got_frame = 0;
create();
}

void AVFile::run()
{
AVFrame frame;
int got_frame;

AVPacket packet;
int packet_size;
uint8_t *packet_data;

AVFrame frame;
AVPacket packet;
DECLARE_ALIGNED(16,uint8_t,shadow)[AVCODEC_MAX_AUDIO_FRAME_SIZE * 4];

while (av_read_frame(formatCtx, &packet) == 0) {
if (packet.stream_index == audioStream) {
// make shure that we will be able to free it later
packet_size = packet.size;
packet_data = packet.data;

// decode frames till packet contains data
while (packet.size > 0) {
avcodec_get_frame_defaults(&frame);
len = avcodec_decode_audio4(codecCtx, &frame, &got_frame, &packet);
int len = avcodec_decode_audio4(codecCtx, &frame, &got_frame, &packet);
if (len < 0) {
break;
break; // probably corrupted packet
}

packet.data += len;
packet.size -= len;

if (got_frame) {
got_frame = 0;
// do some magic

int decoded_size = av_samples_get_buffer_size(NULL, codecCtx->channels, frame.nb_samples, codecCtx->sample_fmt, 1);
uint8_t *decoded_data = frame.data[0];
qDebug() << "Got frame:" << frame.nb_samples << " with size: " << decoded_size;

// TODO: stream params can be changed on the fly, add moare checks
if (!swrCtx &&
codecCtx->channel_layout != av_get_default_channel_layout(2) ||
codecCtx->sample_fmt != AV_SAMPLE_FMT_FLT ||
codecCtx->sample_rate != 44100) {
allocSWR();
}

if (swrCtx) {
uint8_t *shadow_array[] = { shadow };
const uint8_t *input_array[] = { frame.data[0] };
// todo: check original code^ some nasty shit inside
int ret = swr_convert(swrCtx, shadow_array, AVCODEC_MAX_AUDIO_FRAME_SIZE, input_array, decoded_size);
if (ret > 0) {
fillRing(reinterpret_cast<float *>(shadow), ret*2/4);
}
} else {
fillRing(reinterpret_cast<float *>(frame.data[0]), decoded_size);
}
}
}

// restore original size and pointer
packet.size = packet_size;
packet.data = packet_data;
}

// free packet data, reuse structure
av_free_packet(&packet);
}
}

void AVFile::close()
{
// Free codec context
if (codecCtx) {
avcodec_close(codecCtx);
av_freep(&codecCtx); // todo: check that context freed properly
av_freep(&codecCtx); // free context
codecCtx = 0;
}
// Free format context and close file and so on

if (formatCtx) {
avformat_close_input(&formatCtx);
}
// free swr context

if (swrCtx) {
swr_free(&swrCtx);
}
// reset audio stream

audioStream = -1;
// free memory ring

if (ring) {
delete ring;
}
// object now ready to be reused
}

size_t AVFile::pull(float * buffer, size_t size)
{
return ring->pull(buffer, size);
if (!ring)
return 0;

size_t ret = ring->pull(buffer, size);
conditon.signal();
return ret;
}

void AVFile::allocRing()
{
ring = new MemRing<float>(44100 * 8 * codecCtx->channels);
ring = new MemRing<float>(44100 * 8 * 2);
if (!ring)
throw AVException("Unable to allocate ring");
}


void AVFile::allocSWR()
{
swrCtx = swr_alloc_set_opts(0, av_get_default_channel_layout(2), AV_SAMPLE_FMT_FLT, 44100,
codecCtx->channel_layout, codecCtx->sample_fmt, codecCtx->sample_rate,
0, 0);
codecCtx->channel_layout, codecCtx->sample_fmt, codecCtx->sample_rate,
0, 0);

if (!swrCtx)
throw AVException("Unable to allocate swresample context");

swr_init(swrCtx);
}

void AVFile::fillRing(float * buffer, size_t size)
{
// qDebug() << "AVFile: pushing data to the ring" << size
// << "ring free space:" << ring->writeSpace()
// << "ring used space:" << ring->readSpace();

while (ring->writeSpace() < size) {
conditon.lock();
conditon.wait(); // magic
conditon.unlock();
}

ring->push(buffer, size);
}
10 changes: 8 additions & 2 deletions avfile.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,25 @@
#define AVFILE_H

#include <stddef.h>
#include "avcondition.h"
#include "avthread.h"

struct AVFormatContext;
struct AVCodecContext;
struct SwrContext;

template<typename T> class MemRing;

class AVFile

class AVFile : private AVThread
{
public:
AVFile();
virtual ~AVFile();

void open(const char *);
void runDecoder();
void startDecoder();
void run();
void close();

size_t pull(float * buffer, size_t size);
Expand All @@ -27,9 +31,11 @@ class AVFile
SwrContext *swrCtx;
int audioStream;
MemRing<float> *ring;
AVCondition conditon;

void allocRing();
void allocSWR();
void fillRing(float * buffer, size_t size);
};

#endif // AVFILE_H
30 changes: 30 additions & 0 deletions avmutex.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#include "avmutex.h"

AVMutex::AVMutex(): mutex()
{
pthread_mutex_init(&mutex, NULL);
}

AVMutex::~AVMutex()
{
pthread_mutex_destroy(&mutex);
}

bool AVMutex::lock()
{
if (pthread_mutex_lock(&mutex) != 0) {
return false;
}

return true;
}

bool AVMutex::unlock()
{
if (pthread_mutex_unlock(&mutex) != 0)
{
return false;
}

return true;
}
19 changes: 19 additions & 0 deletions avmutex.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#ifndef AVMUTEX_H
#define AVMUTEX_H

#include <pthread.h>

class AVMutex
{
public:
explicit AVMutex();
virtual ~AVMutex();

bool lock();
bool unlock();

protected:
pthread_mutex_t mutex;
};

#endif // AVMUTEX_H
Loading

0 comments on commit a5a2a6b

Please sign in to comment.