Claudio Bertozzi a écrit :
hallo,
could someone tell me if is possible and how to read and decode an audio
and/or video AVPacket from a previous created list of AVPacket read from a
file instead that read directly with av_read_frame function called frame
after frame?
yes, you can store all packets in a list and read whatever packet you
want in that list after (if your AvCodecCtx is correctly initialized)
I join a test program I made from various examples I fouded, it's really
basic and full of bugs but it was just to test to separate reading /
decoding / and playing step and is only made for audio.
in a first step it read all packets and store into a buffer
in a second step it read all stored packets, decode them and save audio
samples into another buffer
and at last it play the decoded audio buffer using OSS
My problem is that after stored all the frame in a list of packets, when I
grab one and pass it at the av_decode... functions, they returned me an
error and never decode the frames.
check if you AvCodecCtx is correctly initialized
I suppose that the av_read_... and/or av_decode_... functions write some
infos in the AVFormatContext or AVCodecContext functions after the read and
decode of a packet. If that is true, what can I do to tell at the structures
to decode the correct packet in my sequence?
I hope to have not made too much mess in the description of my problem.
Please write some feedback ;)
bye
claudio
I hope that help
Yvan
/// \Description : lecture d'un fichier audio decode grace a libavcodec/format et joue via OSS
///
/// V1 : lecture en 3 etapes : 1) extraction des paquets encodes vers un buffer indexe
/// 2) decodage des paquets du buffer vers un autre buffer (qui contiendra donc les echantillons audio decodes)
/// 3) lecture des echantillons depuis le buffer audio vers OSS
///
/// \Author : Yvan LABADIE
#include <stdio.h>
#include <iostream>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/soundcard.h>
#include <vector.h>
extern "C" {
#define __STDC_CONSTANT_MACROS
#define __STDC_LIMIT_MACROS
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
}
void audio_decode_example(const char *outfilename, const char *filename);
using namespace std;
typedef struct frame_t {
unsigned int size;
unsigned char *data;
}frame_t;
////////////////////// VARIABLES ///////////////////////
short audio_buffer[8*1024*1024]; //buffer pour stocker les echantillons audio decodes
short samples[AVCODEC_MAX_AUDIO_FRAME_SIZE]; //samples audio decodes correspondant a un paquet audio encode
AVFormatContext *pFormatCtx;
AVCodecContext *pACodecCtx;
AVCodec *pACodec;
int numBytes;
int i;
int audioStream;
double aFrameRate;
short *buf_ptr;
vector<frame_t> frames;
AVPacket pkt;
int len;
int data_size;
unsigned char *ptr;
unsigned char buffer[4*1024*1024]; //buffer pour stocker les paquets audio encodes
long int frame_ptr=0;
long int seek_pos=0;
int ret;
long int timeStamp;
long int pos;
int duration;
int arg;
int status;
int fd;
short *se; // samples pour encoder une frame MP3
unsigned long int write_ptr = 0;
unsigned long int read_ptr = 0;
/////////////////////////////////////////////////////////
inline void OSSinit() {
//// Sortie Audio, on utilise OSS pour simplifier les choses
puts("openning audio device");
fd = open("/dev/dsp", O_RDWR, O_SYNC);
if (fd < 0) {
perror("open of /dev/dsp failed");
exit(1);
}
arg = 16; //16 bits
status = ioctl(fd, SOUND_PCM_WRITE_BITS, &arg);
if (status == -1)
perror("SOUND_PCM_WRITE_BITS ioctl failed");
if (arg != 16)
perror("unable to set sample size");
arg = 2; //Stereo
status = ioctl(fd, SOUND_PCM_WRITE_CHANNELS, &arg);
if (status == -1)
perror("SOUND_PCM_WRITE_CHANNELS ioctl failed");
if (arg != 2)
perror("unable to set number of channels");
arg = 44000; //44000Hz
status = ioctl(fd, SOUND_PCM_WRITE_RATE, &arg);
if (status == -1)
perror("SOUND_PCM_WRITE_WRITE ioctl failed");
////////////////////////////////////////////////////////
puts("audio device open");
}
/////////////////////////////////////////////////////////
inline void openFile(char * file) {
avcodec_init(); //initialize codecs manager (ffmpeg)
av_register_all(); // Register all formats and codecs
puts("ffmpeg initialized");
// Open media file
status = av_open_input_file(&pFormatCtx, file, NULL, 0, NULL);
if(status!=0){
printf("[ERR (%i)]cannot open input file [%s]\n",status, file);
exit(-1); // Couldn't open file
}
// Retrieve stream information
if(av_find_stream_info(pFormatCtx)<0) {
puts("cannot find stream info");
exit(-1); // Couldn't find stream information
}
puts("dump format...");
// Dump information about file onto standard error
dump_format(pFormatCtx, 0, file, false);
puts("find stream...");
// Find the first audio stream
audioStream=-1;
for(i=0; i<pFormatCtx->nb_streams; i++) {
if(pFormatCtx->streams[i]->codec->codec_type==CODEC_TYPE_AUDIO) {
aFrameRate = av_q2d(pFormatCtx->streams[i]->r_frame_rate);
audioStream=i;
break;
}
}
printf("channels = %i | sample rate = %d | bitrate = %d | bit per sample = %i\n", pFormatCtx->streams[audioStream]->codec->channels, pFormatCtx->streams[audioStream]->codec->sample_rate, pFormatCtx->streams[audioStream]->codec->bit_rate, pFormatCtx->streams[audioStream]->codec->bits_per_coded_sample);
printf("packet size= %i\n", pFormatCtx->packet_size);
if(audioStream==-1) {
puts("[ERR]Didn't find an audio stream");
exit(-1);
}
// Get a pointer to the codec context for the video stream
pACodecCtx=pFormatCtx->streams[audioStream]->codec;
// Find the decoder for the audio stream
pACodec=avcodec_find_decoder(pACodecCtx->codec_id);
if(pACodec==NULL) {
puts("[ERR]audio codec NOT FOUNDED");
exit(-1); // Codec not found
}
// Ouvre le codec
if(avcodec_open(pACodecCtx, pACodec)<0) {
puts("[ERR] openning Codec");
exit(-1);
}
}
/////////////////////////////////////////////////////////
inline void readFrames() {
//lecture fichier => enregistrement des paquets dans un buffer et indexation
puts("we're gonna read some frames");
frames.empty();
frame_t newFrame;
//ret = av_seek_frame(pFormatCtx, audioStream, 0, 0/*AVSEEK_FLAG_BYTE*/);
while(1) {
if(av_read_frame(pFormatCtx, &pkt)<0) {
puts("Read ERROR");
exit(-1);
}
ptr = pkt.data;
len = pkt.size;
timeStamp = pkt.pts;
pos = pkt.pos;
//printf("TS[%li] | pos=%li | readed len = %i\n", timeStamp, pos, len);
if(pkt.stream_index==audioStream){
newFrame.size = len;
newFrame.data = &buffer[write_ptr];
frames.push_back(newFrame);
for (i=0 ; i<len ; i++) {
buffer[write_ptr] = *ptr;
write_ptr++;
if(write_ptr >= 1*1024*1024) {
puts ("buffer FULL!");
break; //on s'embete pas avec le buffer circulaire juste pour le test...
}
ptr++;
}
}
if(write_ptr >= 1*1024*1024 ) {
break; //on s'embete pas avec le buffer circulaire juste pour le test...
}
}
puts("fichier lu");
}
/////////////////////////////////////////////////////////
inline void decode() {
puts("decode...");
//decodage avec index des paquets
buf_ptr = audio_buffer;
for (i=0 ; i< 400; i++) {
ptr = frames[i].data;
len = frames[i].size;
while(len>0) { // Tant que tout n'a pas ete decode
data_size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
ret = avcodec_decode_audio2(pACodecCtx, samples, &data_size, (const uint8_t*)(ptr), len);
printf("ret = %i | data_size = %i\n", ret, data_size);
if(ret<0) {
puts("decode error");
break;
}
len-=ret;
ptr+=ret;
if (data_size > 0) {
for (int j=0 ; j< data_size>>1 ; j++) {
*buf_ptr = samples[j];
buf_ptr++;
}
}
}
}
}
/////////////////////////////////////////////////////////
inline void playAudio() {
//lecture des echantillons audio
char * aud_ptr;
aud_ptr = (char *)audio_buffer;
i=0;
int wrote;
do {
wrote = write(fd, aud_ptr, 512); // if a frame has been decoded, output it
if (wrote > 0) {
aud_ptr+=wrote;
}
i++;
} while (aud_ptr<(char *)buf_ptr);
}
/////////////////////////////////////////////////////////
int main(int argc, char *argv[]) {
OSSinit();
openFile(argv[1]);
readFrames();
decode();
playAudio();
//////////////////////// exit stuff...
close(fd);
avcodec_close(pACodecCtx);
av_close_input_file(pFormatCtx);
return 0;
}
_______________________________________________
libav-user mailing list
[email protected]
https://lists.mplayerhq.hu/mailman/listinfo/libav-user