Форум программистов, компьютерный форум, киберфорум
Наши страницы
C++ Qt
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.67/9: Рейтинг темы: голосов - 9, средняя оценка - 4.67
FYBVFPFYBC
0 / 0 / 0
Регистрация: 19.01.2010
Сообщений: 30
1

QDataStream + OGG + OpenAL

03.09.2012, 00:45. Просмотров 1568. Ответов 14
Метки нет (Все метки)

Задача в том, чтобы считать из qt-ресурса .ogg-файл с помощью QFile, передать его ogg-кодеку с помощью QDataStream и воспроизвести декодированный wav с помощью OpenAL. Трудности на этапе QDataStream >> Ogg Vorbis. Функция ov_open_callbacks(...) из vorbis-api принимает как источник данных указатель на IFSTREAM. Естественно, если я подсовываю ей QDataStream - всё падает. Можно ли как-нибудь перегнать из QDataStream в аналог ifstream, и стоит ли это делать? Может быть есть более разумные способы достать ogg из qt-ресурса и передать на кодек?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
03.09.2012, 00:45
Ответы с готовыми решениями:

Ресурсы QT, QDataStream и OpenAL
Во время проигрывания семплов (WAV / 16 бит / 44100 Hz) слышны щелчки в конце...

OpenAL и ALUT
Привет всем! В общем, нужна программа для воспроизведения ogg и wav через...

QDataStream не работает
Буквально недавно создавал тему по похожей проблеме, но там все решилось...

QDataStream и double
Добрый день коллеги. Столкнулся с проблемой чтения типа double из бинарного...

Работа с QDataStream
Здравствуйте, уважаемые форумчане! Подскажите пожалуйста, в чем могут...

14
NoMasters
Псевдослучайный
1909 / 1120 / 90
Регистрация: 13.09.2011
Сообщений: 3,178
03.09.2012, 00:57 2
Цитата Сообщение от FYBVFPFYBC Посмотреть сообщение
Функция ov_open_callbacks(...) из vorbis-api принимает как источник данных указатель на IFSTREAM.
Где это она его принимает?
1
Maxim Prishchepa
Эксперт С++
1924 / 1036 / 109
Регистрация: 29.03.2010
Сообщений: 3,167
03.09.2012, 00:59 3
передавайте как указатель на считанные данные, в чем проблема то? (я не знаю, что там и как принимает, но это средство универсальное и С++ славится именно этим)
1
FYBVFPFYBC
0 / 0 / 0
Регистрация: 19.01.2010
Сообщений: 30
03.09.2012, 01:40  [ТС] 4
Падает на вызове ov_open_callbacks(...):
Код
QFile qfile( ":/project/Resources/AUDIO.ogg" );
if( !qfile.open( QIODevice::ReadOnly ))
	{
		return false;
	}

OggVorbis_File *oggvorbisfile = new OggVorbis_File;

// структура для файл-инфо и инициализация указателей на некоторые ф-ии vorbis 
SndInfo *sndinfo = new SndInfo;
ov_callbacks  cb;
cb.seek_func  = SeekOgg;
cb.read_func  = ReadOgg;
cb.tell_func  = TellOgg;
cb.close_func = CloseOgg;

QByteArray qbytearray = qfile.readAll(); // читаем всё из qfile

if ( ov_open_callbacks( &qbytearray, oggvorbisfile, NULL, -1, cb ) < 0 )  // здесь падает
	{
		return false;
	}
Необработанное исключение в "0x104327c7 (msvcp100d.dll)" в "project.exe": 0xC0000005: Нарушение прав доступа при чтении "0x00450200".
0
Humanoid
Почетный модератор
9943 / 3847 / 343
Регистрация: 12.06.2008
Сообщений: 11,363
03.09.2012, 08:36 5
Передавать сторонней функции указатель на QByteArray - не слишком правильно. Да и длину не указал. Попробуй
C++ (Qt)
1
if ( ov_open_callbacks( qbytearray.data(), oggvorbisfile, NULL, qbytearray.size(), cb ) < 0 )
Но это просто предположение... я с ogg не работал.
2
NoMasters
Псевдослучайный
1909 / 1120 / 90
Регистрация: 13.09.2011
Сообщений: 3,178
03.09.2012, 14:48 6
Там же просто произвольный указатель, который будет использоваться для чтения при помощи тех функций, которые передаются в последнем параметре, сам vobris ничего с ними не делает. И чего им там надо для работы, лучше знать тебе.
1
FYBVFPFYBC
0 / 0 / 0
Регистрация: 19.01.2010
Сообщений: 30
03.09.2012, 22:30  [ТС] 7
Теперь передаю указатель так:
Код
ov_open_callbacks( qbytearray.data(), oggvorbisfile, NULL, qbytearray.size(), cb )
Вот одна из реализаций (должна сбрасывать текущее состояние и устанавливать относительную позицию чтения, т.е. реагировать на параметр int whence ):
Код
// void *datasource - это qbytearray.data()
int SeekOgg( void *datasource, ogg_int64_t offset, int whence )
{
  istream *File = reinterpret_cast<istream*>( datasource );
  ios_base::seekdir Dir;
  File->clear();   // здесь падает 
  switch( whence ) 
  {
    case SEEK_SET: Dir = ios::beg;  break;
    case SEEK_CUR: Dir = ios::cur;  break;
    case SEEK_END: Dir = ios::end;  break;
    default: return -1;
  }
  File -> seekg(( streamoff ) offset, Dir ); //если не вызывать clear(), то падает здесь
  return ( File -> fail() ? -1 : 0 );
}
Реализация ф-ии чтения:
Код
// void *datasource - это qbytearray.data()
size_t ReadOgg( void *ptr, size_t size, size_t nmemb, void *datasource )
{
	istream *File = reinterpret_cast<istream*>( datasource );
	File -> read(( char * ) ptr, size * nmemb ); // упало бы наверняка здесь
	return File -> gcount();
}
Можно ли вообще не приводить к istream, а использовать только QFile и, например, QDataStream?
0
NoMasters
Псевдослучайный
1909 / 1120 / 90
Регистрация: 13.09.2011
Сообщений: 3,178
04.09.2012, 15:54 8
Можно(нужно) использовать только QFile. На кой чёрт тут попытки ввернуть QDataStream и тем более стандартные потоки? Вобрис интересуют только конкретные куски данных, его совершенно не волнует, откуда они берутся.
0
FYBVFPFYBC
0 / 0 / 0
Регистрация: 19.01.2010
Сообщений: 30
05.09.2012, 20:13  [ТС] 9
Эти реализации со стандартными потоками я нашла на просторах. Если это настолько просто, может подскажете конкретной строчкой кода как переделать, к примеру, ф-ию чтения
Код
size_t ReadOgg( void *ptr, size_t size, size_t nmemb, void *datasource )
Вы, видимо, работали с vorbis. Я не до конца понимаю как взаимодействуют эти четыре функции, но этот вопрос в другую ветку форума. В документации QFile не нашла некоторых аналогичных стандартным потокам функций, например, gcount(). Все четыре функции, насколько мне понятно, возвращают значения vorbis'у, а не мне.
0
NoMasters
Псевдослучайный
1909 / 1120 / 90
Регистрация: 13.09.2011
Сообщений: 3,178
05.09.2012, 23:31 10
Банально же:
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
size_t ReadOgg(void *ptr, size_t size, size_t nmemb, void *datasource)
{
    QFile *file = (QFile*)datasource;
    if(file->atEnd())
        return 0;
    qint64 rlen = file->read((char*)ptr, size * nmemb);
    if(rlen < 0)
    {
        errno = file->error();
        return 0;
    }
    return rlen;
}
Описание, чего должны делать/возвращать функции здесь.
З.Ы. не тестил
1
FYBVFPFYBC
0 / 0 / 0
Регистрация: 19.01.2010
Сообщений: 30
07.09.2012, 15:09  [ТС] 11
По-прежнему падает на самом чтении в ReadOgg. tell_func и seek_func указывают на NULL, т.к. файл нужно считать сразу целиком без лишних вызовов.
Код
// инициализируем QFile из ресурса
QFile qfile( ":/project/Resources/Audio.ogg" );
if( !qfile.open( QIODevice::ReadOnly ))
  return false;

// инициализируем указатели на ф-ии обратного вызова vorbis
ov_callbacks  cb;
cb.seek_func = NULL;
cb.read_func = ReadOgg;
cb.tell_func  = NULL;
cb.close_func = CloseOgg;

OggVorbis_File *oggVF = new OggVorbis_File;
ov_open_callbacks( &qfile, oggVF, NULL, 0, cb );
// Реализация ф-ии чтения
size_t ReadOgg( void *ptr, size_t size, size_t nmemb, void *datasource )
{
   QFile *file = ( QFile* )datasource;
   if( !file -> open( QIODevice::ReadOnly ))
      return 0;
   if( file -> atEnd() )
      return 0;
   qint64 qsize = file -> size(); // размер видит правильно
   qint64 rlen = file -> read(( char* )ptr, qsize ); // здесь падает
   if( rlen < 0 )
   {
      errno = file -> error();
      return 0;
   }
   return rlen;
}
ReadOgg принимает два параметра от самого ворбис size_t size и size_t nmemb. Во время выполнения это 1 и 2048 соответственно, т.е. "с точки зрения" ворбис ReadOgg должна прочитать 1*2048 = 2 килобайта за вызов. Нужно просто игнорировать эти параметры?
0
NoMasters
Псевдослучайный
1909 / 1120 / 90
Регистрация: 13.09.2011
Сообщений: 3,178
07.09.2012, 16:45 12
Не надо ничего игнорировать, моя функция рабочая, только что затестил, её менять не надо(тем более не в лучшую сторону, зачем строки 19-20?). Проблема где-то в другом месте.
0
FYBVFPFYBC
0 / 0 / 0
Регистрация: 19.01.2010
Сообщений: 30
07.09.2012, 17:34  [ТС] 13
SeekOgg и TellOgg это NULL в моём случае, и если использую ваш код, то ReadOgg вызывается видимо только один раз, читает 2 килобайта, после чего вызов ov_open_callbacks(...) завершается без успеха (возвращает < 0). И если не использую QFile::open (строки 19, 20), то условие
Код
if( file -> atEnd() )
        return 0;
выполняется и ReadOgg возвращает 0.
Ваш пример для случая когда seek_func и tell_func указывают на NULL тоже актуален?

Добавлено через 18 минут
Если ваш пример не актуален для случая загрузки файла целиком, то не затруднит ли выложить здесь код функций SeekOgg и TellOgg, которые вы использовали в тесте своего кода? Хотя бы частями буду загружать, пока не разберусь до конца.
0
NoMasters
Псевдослучайный
1909 / 1120 / 90
Регистрация: 13.09.2011
Сообщений: 3,178
07.09.2012, 18:12 14
Мой пример актуален не зависимо от seek_func и tell_func. Всё вызывается столько раз, сколько надо и отлично работает и при нулях в остальных функциях, при этом совершенно параллельно, читать целиком или по частям.
Цитата Сообщение от FYBVFPFYBC Посмотреть сообщение
после чего вызов ov_open_callbacks(...) завершается без успеха
Его надо всего один раз вызывать, осильте уже прочтение документации.
1
FYBVFPFYBC
0 / 0 / 0
Регистрация: 19.01.2010
Сообщений: 30
07.09.2012, 19:35  [ТС] 15
Уже осилила. Кое-что внутри ov_open_callbacks оставалось не понятным, но вызываю я её один раз Спасибо за ответ
0
07.09.2012, 19:35
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
07.09.2012, 19:35

QDataStream + char
Вообщем такая проблема. struct STRUCT_PACKET_DATA { quint64...

QByteArray и QDataStream
Помогите разобраться с двумя типами данных QByteArray и QDataStream. Для...

QDataStream и ulong
Есть код: QFile file(fname); file.open(QIODevice::WriteOnly); QDataStream...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
15
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru