주 메뉴 열기

wwiki β

바뀜

FFmpeg 개발

10,413 바이트 추가됨, 2022년 4월 10일 (일) 02:09
avcodec_send_packet
[[FFmpeg]] 명령 사용을 먼저 해 볼 수 있다.
 
== libavformat(lavf) ==
오디오 비디오 포맷 라이브러리 I/O and Muxing(Mux: '''mu'''ltipl'''x'''er, 다중통신장치)/Demuxing Library.
다양한 미디어 컨테이너 형식을 처리하기 위한 라이브러리입니다. 데이터에 액세스하기 위한 여러 프로토콜(예: 파일, tcp, http 및 기타)을 지원하는 I/O모듈이 있습니다. lavf를 사용하기 전에 av_register_all()을 호출하여 컴파일된 모든 muxer, 디먹서 및 프로토콜을 등록해야 합니다. libavformat의 네트워크 기능을 사용하려면 avformat_network_init()를 호출해야 합니다.
멀티플렉싱 및 디먹싱에 사용되는 기본 lavf 구조는 AVFormatContext이며, 읽거나 쓰는 파일에 대한 모든 정보를 내보냅니다.
가장 중요한 것은 AVFormatContext 에 AVFormatContext에 다음이 포함되어 있습니다.
* '''입력 또는 출력 입출력 컨테이너 포맷(AVInputFormat, AVOutputFormat)''': 입력을 위해 자동 감지되거나 사용자가 설정합니다. 항상 출력을 위해 사용자에 의해 설정됩니다.* '''AVStreams'''스트림(파일에 저장된 모든 기본 스트림의 describeAVStream**)'''의 배열''': 오디오스트림, 비디오스트림, 자막스트림 등. 오디오스트림과 자막스트림은 언어별로 존재할 수 있다.* '''I/O 컨텍스트O컨텍스트(AVIOContext)''': lavf에 의해 열리거나 입력을 위해 사용자가 설정하며, 항상 출력을 위해 사용자가 설정합니다.<ref> 암호화된 데이터를 전달하는 경우에 직접 할당하여 사용하는 듯 하다. </ref>
=== (de)muxers에 옵션 전달 ===
libavformat기능을 쿼리하거나 핵심구조체를 할당하는 함수들
===== int avformat_network_init (void) ====='''파라미터''': void  '''반환''': int  
이것은 선택 사항이며 더 이상 권장되지 않습니다.
==== 디먹싱 ====
디먹서는 미디어 파일을 읽고 패킷(chunks of data, [[FFmpeg#AVPacket|AVPacket]])으로 분리한다.
패킷은 하나의 기본 스트림에 속하는 하나 개 이상의 인코딩 된 프레임을 포함한다. lavf API에서는 파일을 열기 위해서 avformat_open_input()함수를 호출한 후, 단일패킷을 읽기 위해서 av_read_frame()함수를 호출한 후, 마지막으로 avformat_close_input()을 호출해서 정리한다.
===== '''미디어 파일 열기 ====='''  파일을 열기 위해서는 avformat_open_input()함수에 파일의 url만은 url을 전달해야 한다. 다음 코드처럼.<syntaxhighlight lang="c">
const char *url = "file:in.mp3";
AVFormatContext *s = NULL;
</syntaxhighlight>파일 읽기가 끝난 후에 avformat_close_input()을 호출해야 한다. 파일과 관련된 모든 것들을 해제한다.
===== '''열린 파일에서 읽기 =====''' 
열린 AVFormatContext에서 데이터를 읽는 것은 av_read_frame()를 반복적으로 호출하면 된다. 호출할 때마다 인코딩된 데이터인 하나의 AVStream을 포함한 AVPacket(AVPacket.stream_index번호로 식별된다.)을 리턴한다. 데이터를 디코딩하려면 패킷을 libavcodec의 디코딩 함수인 avcodec_send_packet()이나 avcodec_decode_subtitle2()에 직접 전달할 수 있다.
[[AVPacket.pts]], [[AVPacket.dts]], [[AVPacket.duration]]은 타이밍정보가 설정된다. 만약 스트림이 제공하지 않는다면 pts와 dts가 AV_NOPTS_VALUE이고 duration은 0이다. 타이밍 정보는 AVStream.time_base단위로 표시됩니다. 즉, 시간단위를 곱하여 초로 변환한다.
반환된 패킷에 [[AVPacket.buf가 buf]]가 설정되어 있으면 패킷이 동적으로 할당되므로 사용자가 이를 무한정 유지할 수 있다. 그렇지 않으면 AVPacket.buf는 NULL이고, 패킷 데이터는 디먹서 안의 정적 저장소에 백업되고(backed) 파일을 닫거나 av_read_frame()를 호출할 때까지만 유효하다. 더 사용하려면 av_dup_packet()함수가 av_malloc()를 호출해서 그것을 복사할 수 있다. 두 경우 모두 더 이상 필요하지 않으면 av_packet_unref()를 호출해서 패킷을 해제한다.  ===== Functions ===== ====== av_read_frame ======Return the next frame of a stream. '''파라미터''' * AVFormatContext * s* AVPacket * pkt  '''반환''': int(성공이면 0, 에러거나 파일이 끝났으면 음수) 이 함수는 파일에 저장된 데이터를 반환하고, 디코더를 위한 유효한 프레임이 있는지 확인하지 않는다. 파일에 저장된 내용을 프레임으로 분할하고 호출할 때마다 하나씩 반환한다. 디코더는 디코딩에 가능한 최대 정보를 제공하기 위해 유효한 프레임간의 유효하지 않은 데이터를 생략하지 않는다.  만약 pkt->buf가 NULL이면 패킷(pkt)은 다음 av_read_frame() 또는 avformat_close_input()을 호출할 때까지 유효합니다. 그렇지 않으면 패킷은 무기한 유효하다. 두 경우 모두 av_packet_unref()를 호출하여 더이상 필요없는 패킷을 해제해야 한다. 비디오의 경우에는 정확히 하나의 프레임이 포함된다. 오디오의 경우 비디오 프레임마다 정수개의 프레임을 포함한다.(가령, PCM 혹은 ADPCM 데이터처럼 여러개의 오디오 스트림처럼) 만약 오디오 프레임들이 가변크기를 가진다면(MPEG 오디오처럼) 한개의 프레임을 포함한다. pkt->pts, pkt->dts and pkt->duration은 항상 AVStream.time_base 단위로 정확한 값들이 설정된다. (만약 포맷이 그걸 제공하지 않으면 추측된다.) 비디오 프레임이 B-frames이면 pkt->ptsd은 AV_NOPTS_VALUE이다. 그래서 페이로드의 압축을 해제하지 않으면 pkt->dts를 사용하는 것이 좋다. ====== av_packet_unref ======패킷을 정리한다. '''파라미터''' * AVPacket * pkt 패킷이 참조하는 버퍼를 참조해제하고 나머지 패킷필드를 기본값으로 재설정한다. == libavcodec ==Encoding/Decoding Library. === Modules === ==== Decoding ==== ===== Fuctions ===== ====== av_parser_parse2 ======Parse a packet. parameter * AVCodecParserContext *s* AVCodecContext *avctx* uint8_t **poutbuf* int *poutbuf_size* const uint8_t *buf: 인코딩된 데이터* int buf_size* int64_t pts* int64_t dts* int64_t pos return: int s = av_parser_init(codec->id);  avctx = avcodec_alloc_context3(codec);  ret = av_parser_parse2(s, avctx, &pkt->data, &pkt->size, data, data_size, AV_NOPTS_VALUE, AV_NOPTS_VALUE, 0); ====== avcodec_send_packet ======'''파라미터''' * AVCodecContext * avctx 코덱 콘텍스트* const AVPacket * avpkt [in]  <blockquote>입력값. 일반적으로 단일 비디오 프레임이거나 몇 개의 완성된 오디오 프레임들이다. 패킷의 소유권은 호출한 곳에 유지되고, 디코더는 그 패킷의 값을 변경하지 않을 것이다. 디코더는 패킷 데이터에 대한 참조를 생성할 수 있다.(혹은 레퍼런스 카운트되지 않는다면 복사할 것이다.) 오래된 함수들과 다르게 패킷은 항상 전체가 소비되고, 패킷이 어떤 오디오 코덱처럼 여러 프레임들을 포함한다면 avcodec_receive_frame()함수를 여러 번 호출해야 할 것이다. avpkt가 NULL이거나 혹은 avpkt의 data가 NULL이거나 size가 0인 경우에는 스트림의 끝이라는 신호인 flush pakcet으로 간주된다. 처음 flush packet을 보내는 것은 성공을 반환한다. 다시 보내는 것은 불필요하고 AVERROR_EOF를 리턴할 것이다. 만약 디코더가 여전히 버퍼된 프레임을 가지고 있다면, flush packet을 보낸 후에 리턴한다.</blockquote>'''반환''': int<blockquote>성공이면 0, 그렇지 않으면 음수인 에러코드를 리턴한다. </blockquote>원시 패킷 데이터를 디코더에 입력으로 제공한다.  내부적으로 이 함수를 호출하면 각 패킷의 디코딩하는 것에 영향을 미치는 AVCodecContext의 관련된 필드를 복사할 것이다. 그리고 실제로 패킷이 디코딩되었을 때 적용한다.  '''경고'''  입력버퍼인 avpkt->data는 어떤 최적화된 bitstream reader는 끝을 넘어서 한번에 32비트나 64비트를 읽기 때문에 실제 읽은 바이트보다 AV_INPUT_BUFFER_PADDING_SIZE가 커야 한다.  동일한 AVCodecContext를 avcodec_decode_video2()와 같은 오래된 함수와 혼용하지 마라. 기대하지 않았던 값을 리턴할 것이다.  '''주의'''  AVCodecContext는 디코더에 전달하기 전에 avcodec_open2()함수를 호출하여 열어야 한다.  ==== Core functions/structures. ==== ===== Modules ===== ======[[AVPacket]]======== 예제 == === decode_video.c ===<syntaxhighlight lang="c">/* * Copyright (c) 2001 Fabrice Bellard * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. *//** * @file * video decoding with libavcodec API example * * @example decode_video.c */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <libavcodec/avcodec.h>#define INBUF_SIZE 4096static void pgm_save(unsigned char *buf, int wrap, int xsize, int ysize, char *filename){ FILE *f; int i; f = fopen(filename,"w"); fprintf(f, "P5\n%d %d\n%d\n", xsize, ysize, 255); for (i = 0; i < ysize; i++) fwrite(buf + i * wrap, 1, xsize, f); fclose(f);}static void decode(AVCodecContext *dec_ctx, AVFrame *frame, AVPacket *pkt, const char *filename){ char buf[1024]; int ret; ret = avcodec_send_packet(dec_ctx, pkt); if (ret < 0) { fprintf(stderr, "Error sending a packet for decoding\n"); exit(1); } while (ret >= 0) { ret = avcodec_receive_frame(dec_ctx, frame); if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) return; else if (ret < 0) { fprintf(stderr, "Error during decoding\n"); exit(1); } printf("saving frame %3d\n", dec_ctx->frame_number); fflush(stdout); /* the picture is allocated by the decoder. no need to free it */ snprintf(buf, sizeof(buf), "%s-%d", filename, dec_ctx->frame_number); pgm_save(frame->data[0], frame->linesize[0], frame->width, frame->height, buf); }}int main(int argc, char **argv){ const char *filename, *outfilename; const AVCodec *codec; AVCodecParserContext *parser; AVCodecContext *c= NULL; FILE *f; AVFrame *frame; uint8_t inbuf[INBUF_SIZE + AV_INPUT_BUFFER_PADDING_SIZE]; uint8_t *data; size_t data_size; int ret; AVPacket *pkt; if (argc <= 2) { fprintf(stderr, "Usage: %s <input file> <output file>\n", argv[0]); exit(0); } filename = argv[1]; outfilename = argv[2]; pkt = av_packet_alloc(); if (!pkt) exit(1); /* set end of buffer to 0 (this ensures that no overreading happens for damaged MPEG streams) */ memset(inbuf + INBUF_SIZE, 0, AV_INPUT_BUFFER_PADDING_SIZE); /* find the MPEG-1 video decoder */ codec = avcodec_find_decoder(AV_CODEC_ID_MPEG1VIDEO); if (!codec) { fprintf(stderr, "Codec not found\n"); exit(1); } parser = av_parser_init(codec->id); if (!parser) { fprintf(stderr, "parser not found\n"); exit(1); } c = avcodec_alloc_context3(codec); if (!c) { fprintf(stderr, "Could not allocate video codec context\n"); exit(1); } /* For some codecs, such as msmpeg4 and mpeg4, width and height MUST be initialized there because this information is not available in the bitstream. */ /* open it */ if (avcodec_open2(c, codec, NULL) < 0) { fprintf(stderr, "Could not open codec\n"); exit(1); } f = fopen(filename, "rb"); if (!f) { fprintf(stderr, "Could not open %s\n", filename); exit(1); } frame = av_frame_alloc(); if (!frame) { fprintf(stderr, "Could not allocate video frame\n"); exit(1); } while (!feof(f)) { /* read raw data from the input file */ data_size = fread(inbuf, 1, INBUF_SIZE, f); if (!data_size) break; /* use the parser to split the data into frames */ data = inbuf; while (data_size > 0) { ret = av_parser_parse2(parser, c, &pkt->data, &pkt->size, data, data_size, AV_NOPTS_VALUE, AV_NOPTS_VALUE, 0); if (ret < 0) { fprintf(stderr, "Error while parsing\n"); exit(1); } data += ret; data_size -= ret; if (pkt->size) decode(c, frame, pkt, outfilename); } } /* flush the decoder */ decode(c, frame, NULL, outfilename); fclose(f); av_parser_close(parser); avcodec_free_context(&c); av_frame_free(&frame); av_packet_free(&pkt); return 0;}</syntaxhighlight><br />
== 외부링크 ==
https://ffmpeg.org/documentation.html
 
== 각주 ==
<references />
[[분류:FFMPEG]]
편집
2,431