Aprendizaje ffmpeg (imprimir la información del archivo correspondiente, extraer información del archivo de audio)

Tabla de contenido

Imprima la información del archivo correspondiente.

Extraer información del archivo de audio


Imprima la información del archivo correspondiente.

# Concepto
Un archivo multimedia es un contenedor y hay muchas secuencias en el contenedor, que están representadas por (secuencia o pista). Cada uno de los diferentes flujos no se cruza y está codificado por diferentes codificadores (las diferentes codificaciones de audio y video son similares), y los datos leídos del flujo son un paquete que contiene uno o más cuadros de datos comprimidos.

```
AVFormatContext: contexto de transmisión de archivos multimedia
AVstream: transmisión multimedia, lectura de transmisión desde un archivo multimedia
AVPacket: obtención de la velocidad de fotogramas de la compresión de la transmisión multimedia
```
Pasos básicos para que FFmpeg opere datos de transmisión:

 **1. Demultiplexación
 2. Flujo de datos
 3. Obtención de paquetes de datos
 4. Liberación de recursos relacionados**
# Imprimir información de flujo multimedia

```cpp
extern "C"
{
    #include <libavutil/log.h>
    #include <libavformat/avformat.h>
}
#ifdef av_err2str
#undef av_err2str
#include <string>
av_always_inline std::string av_err2string(int errnum) {
    char str[AV_ERROR_MAX_STRING_SIZE];
    return av_make_error_string(str, AV_ERROR_MAX_STRING_SIZE, errnum);
}
#define av_err2str(err) av_err2string(err).c_str()
#endif


int main(int argc, char const *argv[])
{   int ret;
    av_log_set_level(   AV_LOG_INFO);
    // 注册信息
    av_register_all();
    AVFormatContext *fmt_ctx=NULL;
    // 打开多媒体文件,制定多媒体文件内容上向文,制定文件地质,指定文件类型,制定传入参数
    ret=avformat_open_input(&fmt_ctx,argv[1],NULL,NULL);
    if(ret<0){
        av_log(NULL,AV_LOG_INFO,"CAN'T OPEN FILE:%s \n",av_err2str(ret));
        return -1;
    }
    // av_dump_format()参数为上下文信息,流的索引值,多媒体文件名,输入流0或者输出流信息
    // 打印媒体流信息
    av_dump_format(fmt_ctx,0,argv[1],0);
    // 带开多媒体文件
    avformat_close_input(&fmt_ctx);
    return 0;
}


------------------------------------------输出信息------ ------------------------------------
Entrada #0, mov,mp4,m4a,3gp,3g2, mj2, de '../source/big_buck_bunny_720p_30mb.mp4':
  Metadatos:
    marca_mayor: isom
    versión_menor: 512
    marcas_compatibles: isomiso2avc1mp41
    tiempo_creación: 1970-01-01T00:00:00.000000Z
    codificador: Lavf53.24.2
  Duración: 00:02:50 .86, tasa de bits: N/A
  Transmisión #0:0(und): Vídeo: h264 (avc1 / 0x31637661), ninguno, 1280x720, 1086 kb/s, 25 fps, 25 tbr, 12800 tbn (predeterminado) Metadatos: tiempo_creación
    :
      1970-01 -01T00:00:00.000000Z
      nombre_controlador: VideoHandler
      ID_proveedor: [0][0][0][0]
  Transmisión #0:1(und): Audio: aac (mp4a / 0x6134706D), 48000 Hz, 6 canales, 383 kb/s (predeterminado) Metadatos: tiempo_creación: 1970-01-01T00:00:
    00.000000Z
      nombre_controlador
      :
      ID_proveedor de SoundHandler: [0][0][0][0]
```

Extraer información del archivo de audio

# Extrae los datos de audio en el archivo multimedia
 1. av_init_packet(): inicializa la estructura del paquete
 2. av_find_best_stream: obtiene el mejor flujo de datos del archivo multimedia
 3. av_read_frame()/av_packet_unref(): lee los paquetes en el flujo, gratis ganar espacio después de su uso

**Debido a la encapsulación en formato ACC, es necesario guardarlo en formato ADTS durante el proceso de encapsulación. En comparación con ADIS, el formato ADTS es más fácil de usar en transmisión y su tamaño es de 7 bytes **
![ Inserte descripción de imagen aquí ](https://img-blog.csdnimg.cn/df7cd41e337949d99a96777a5ad8fb31.png)

 - syncword (que ocupa un total de 12 bits): el encabezado de sincronización representa el comienzo de una trama ADTS, todos los bits se establecen en 1, es decir, 0xFFF - ID (1 bit): identificador MPEG, 0 indica MPEG-4   
 , 1 indica MPEG- 2
 - Capa (2 dígitos): configurado directamente en 00
 - Protection_absent (1 dígito): Indica si se deben verificar errores. 1 sin CRC, 0 tiene perfil CRC: nivel de codificación AAC, 0:
 - Perfil principal (2 bits): 1: LC (el más utilizado), 2: SSR, 3: reservado
 - sampling_frequency_index (identificador de frecuencia de muestreo): frecuencia de muestreo Mark Private bit: establecido directamente en 0, ignore este parámetro al decodificar
 - configuración_canal (3 bits): identificación del número de canal, estructura de diseño de vida
 - original_copy (1 bit): establecido directamente en 0, ignore este parámetro al decodificar
 - inicio (1 bit ): establecido directamente en 0, ignore este parámetro al decodificar

**Información del encabezado variable: adts_variable_header()**
    ![Inserte una descripción de la imagen aquí](https://img-blog.csdnimg.cn/53ec80a625ce43b4beed02289c7a73fa.png)

 - copyright_identification_bit: establecido directamente en 0, ignora este parámetro al decodificar
 - copyright_identification_start: establecido directamente en 0, ignora este parámetro al decodificar
 - aac_frame_lenght: el número de bytes del cuadro de audio actual, el número de bytes de metadatos codificados + el número de archivo bytes de encabezado (0 = = Protection_absent? 7: 9)
 - adts_buffer_fullness: cuando se establece en 0x7FF, significa velocidad de bits variable
 - number_of_raw_data_blocks_in_frames: el número de cuadros de codificación de audio contenidos en el paquete de audio actual, configurado en aac_nums - 1, es decir, establecido en 0 cuando solo hay un cuadro de audio

```cpp
extern "C"
{
   #include <stdio.h>
    #include <libavutil/log.h>
    #include <libavformat/avio.h>
    #include <libavformat/avformat.h> 
}

#define ADTS_HEADER_LEN  7;

static int get_audio_obj_type(int aactype){
    //AAC HE V2 = AAC LC + SBR + PS
    //AAV HE = AAC LC + SBR
    //所以无论是 AAC_HEv2 还是 AAC_HE 都是 AAC_LC
    switch(aactype){
        case 0:
        case 2:
        case 3:
            return aactype+1;
        case 1:
        case 4:
        case 28:
            return 2;
        default:
            return 2;

    }
}

static int get_sample_rate_index(int freq, int aactype){

    int i = 0;
    int freq_arr[13] = {
        96000, 88200, 64000, 48000, 44100, 32000,
        24000, 22050, 16000, 12000, 11025, 8000, 7350
    };

    //如果是 AAC HEv2 或 AAC HE, 则频率减半
    if(aactype == 28 || aactype == 4){
        freq /= 2; 
    }

    for(i=0; i< 13; i++){
        if(freq == freq_arr[i]){
            return i;
        }
    }
    return 4;//默认是44100
}

static int get_channel_config(int channels, int aactype){
    //如果是 AAC HEv2 通道数减半
    if(aactype == 28){
        return (channels / 2); 
    }
    return channels;
}

static void adts_header(char *szAdtsHeader, int dataLen, int aactype, int frequency, int channels){

    int audio_object_type = get_audio_obj_type(aactype);
    int sampling_frequency_index = get_sample_rate_index(frequency, aactype);
    int channel_config = get_channel_config(channels, aactype);

    printf("aot=%d, freq_index=%d, channel=%d\n", audio_object_type, sampling_frequency_index, channel_config);

    int adtsLen = dataLen + 7;

    szAdtsHeader[0] = 0xff;         //syncword:0xfff                          高8bits
    szAdtsHeader[1] = 0xf0;         //syncword:0xfff                          低4bits
    szAdtsHeader[1] |= (0 << 3);    //MPEG Version:0 for MPEG-4,1 for MPEG-2  1bit
    szAdtsHeader[1] |= (0 << 1);    //Layer:0                                 2bits 
    szAdtsHeader[1] |= 1;           //protection absent:1                     1bit

    szAdtsHeader[2] = (audio_object_type - 1)<<6;            //profile:audio_object_type - 1                      2bits
    szAdtsHeader[2] |= (sampling_frequency_index & 0x0f)<<2; //sampling frequency index:sampling_frequency_index  4bits 
    szAdtsHeader[2] |= (0 << 1);                             //private bit:0                                      1bit
    szAdtsHeader[2] |= (channel_config & 0x04)>>2;           //channel configuration:channel_config               高1bit

    szAdtsHeader[3] = (channel_config & 0x03)<<6;     //channel configuration:channel_config      低2bits
    szAdtsHeader[3] |= (0 << 5);                      //original:0                               1bit
    szAdtsHeader[3] |= (0 << 4);                      //home:0                                   1bit
    szAdtsHeader[3] |= (0 << 3);                      //copyright id bit:0                       1bit  
    szAdtsHeader[3] |= (0 << 2);                      //copyright id start:0                     1bit
    szAdtsHeader[3] |= ((adtsLen & 0x1800) >> 11);           //frame length:value   高2bits

    szAdtsHeader[4] = (uint8_t)((adtsLen & 0x7f8) >> 3);     //frame length:value    中间8bits
    szAdtsHeader[5] = (uint8_t)((adtsLen & 0x7) << 5);       //frame length:value    低3bits
    szAdtsHeader[5] |= 0x1f;                                 //buffer fullness:0x7ff 高5bits
    szAdtsHeader[6] = 0xfc;
}

int main(int argc, char *argv[])
{
    int err_code;
    char errors[1024];

    char *src_filename = NULL;
    char *dst_filename = NULL;

    FILE *dst_fd = NULL;

    int audio_stream_index = -1;
    int len;

    AVFormatContext *ofmt_ctx = NULL;
    AVOutputFormat *output_fmt = NULL;

    AVStream *out_stream = NULL;

    AVFormatContext *fmt_ctx = NULL;
    AVFrame *frame = NULL;
    AVPacket pkt;

    av_log_set_level(AV_LOG_DEBUG);

    if(argc < 3){
        av_log(NULL, AV_LOG_DEBUG, "the count of parameters should be more than three!\n");
        return -1;
    }

    src_filename = argv[1];
    dst_filename = argv[2];

    if(src_filename == NULL || dst_filename == NULL){
        av_log(NULL, AV_LOG_DEBUG, "src or dts file is null, plz check them!\n");
        return -1;
    }

    dst_fd = fopen(dst_filename, "wb");
    if (!dst_fd) {
        av_log(NULL, AV_LOG_DEBUG, "Could not open destination file %s\n", dst_filename);
        return -1;
    }

    /*open input media file, and allocate format context*/
    if((err_code = avformat_open_input(&fmt_ctx, src_filename, NULL, NULL)) < 0){
        av_strerror(err_code, errors, 1024);
        av_log(NULL, AV_LOG_DEBUG, "Could not open source file: %s, %d(%s)\n",
               src_filename,
               err_code,
               errors);
        return -1;
    }

    /*retrieve audio stream*/
    if((err_code = avformat_find_stream_info(fmt_ctx, NULL)) < 0) {
        av_strerror(err_code, errors, 1024);
        av_log(NULL, AV_LOG_DEBUG, "failed to find stream information: %s, %d(%s)\n",
               src_filename,
               err_code,
               errors);
        return -1;
    }

    /*dump input information*/
    av_dump_format(fmt_ctx, 0, src_filename, 0);

    frame = av_frame_alloc();
    if(!frame){
        av_log(NULL, AV_LOG_DEBUG, "Could not allocate frame\n");
        return AVERROR(ENOMEM);
    }

    /*initialize packet*/
    av_init_packet(&pkt);
    pkt.data = NULL;
    pkt.size = 0;

    /*find best audio stream*/
    audio_stream_index = av_find_best_stream(fmt_ctx, AVMEDIA_TYPE_AUDIO, -1, -1, NULL, 0);
    if(audio_stream_index < 0){
        av_log(NULL, AV_LOG_DEBUG, "Could not find %s stream in input file %s\n",
               av_get_media_type_string(AVMEDIA_TYPE_AUDIO),
               src_filename);
        return AVERROR(EINVAL);
    }

    /*
     #define FF_PROFILE_AAC_MAIN 0
     #define FF_PROFILE_AAC_LOW  1
     #define FF_PROFILE_AAC_SSR  2
     #define FF_PROFILE_AAC_LTP  3
     #define FF_PROFILE_AAC_HE   4
     #define FF_PROFILE_AAC_HE_V2 28
     #define FF_PROFILE_AAC_LD   22
     #define FF_PROFILE_AAC_ELD  38
     #define FF_PROFILE_MPEG2_AAC_LOW 128
     #define FF_PROFILE_MPEG2_AAC_HE  131
    */

    int aac_type = fmt_ctx->streams[1]->codecpar->profile;
    int channels = fmt_ctx->streams[1]->codecpar->channels;
    int sample_rate= fmt_ctx->streams[1]->codecpar->sample_rate;

    if(fmt_ctx->streams[1]->codecpar->codec_id != AV_CODEC_ID_AAC){
        av_log(NULL, AV_LOG_ERROR, "the audio type is not AAC!\n");
        goto __ERROR;
    }else{
        av_log(NULL, AV_LOG_INFO, "the audio type is AAC!\n"); 
    }

    /*read frames from media file*/
    while(av_read_frame(fmt_ctx, &pkt) >=0 ){
        if(pkt.stream_index == audio_stream_index){

            
            char adts_header_buf[7];
            adts_header(adts_header_buf, pkt.size, aac_type, sample_rate, channels);
            fwrite(adts_header_buf, 1, 7, dst_fd);

            len = fwrite( pkt.data, 1, pkt.size, dst_fd);
            if(len != pkt.size){
                av_log(NULL, AV_LOG_DEBUG, "warning, length of writed data isn't equal pkt.size(%d, %d)\n",
                       len,
                       pkt.size);
            }
        }
        av_packet_unref(&pkt);
    }

__ERROR:
    /*close input media file*/
    avformat_close_input(&fmt_ctx);
    if(dst_fd) {
        fclose(dst_fd);
    }

    return 0;
}


```
 

Supongo que te gusta

Origin blog.csdn.net/qq_44632658/article/details/131741341
Recomendado
Clasificación