Guest User

Untitled

a guest
Oct 3rd, 2024
54
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.87 KB | None | 0 0
  1. extern "C" {
  2. #include <libavformat/avformat.h>
  3. #include <libswscale/swscale.h>
  4. #include <libavutil/imgutils.h>
  5. #include <libavutil/dict.h>
  6. }
  7.  
  8. int error;
  9.  
  10. AVFormatContext* inputFormatContext = NULL;
  11.  
  12. AVFormatContext* outputFormatContext = NULL;
  13. AVCodecContext* encoderContext;
  14. AVCodecContext* decoderContext;
  15. SwsContext *swsCtx = nullptr;
  16. AVPacket* decodePacket;
  17. AVCodec* decoderCodec;
  18.  
  19. uint8_t *dst_data[4];
  20. int dst_linesize[4];
  21.  
  22.  
  23. uint8_t* outputFrameBuffer;
  24.  
  25. AVPacket* encodePacket;
  26.  
  27. AVFrame* inputFrame;
  28. AVFrame* outputFrame;
  29.  
  30. FILE *dst_file;
  31. int dst_bufsize;
  32. int ret;
  33.  
  34. //TODO dimension
  35.  
  36. int main(int argc, char **argv){
  37.  
  38. if(argc < 3){
  39. puts("2 arguments are required, input file and output file.");
  40. return 0;
  41. }
  42.  
  43. char* inputFile = argv[1];
  44. char* outputFile = argv[2];
  45.  
  46. error = avformat_open_input(&inputFormatContext, inputFile, NULL, NULL);
  47.  
  48. if (error) {
  49. return 1;
  50. }
  51.  
  52. error = avformat_find_stream_info(inputFormatContext, NULL);
  53.  
  54. if (error) {
  55. return 1;
  56. }
  57.  
  58.  
  59. int streamIndex = av_find_best_stream(inputFormatContext, AVMEDIA_TYPE_VIDEO, -1, -1, nullptr, 0);
  60.  
  61. if (streamIndex < 0) {
  62. error = AVERROR_UNKNOWN;
  63. return 1;
  64. }
  65.  
  66. AVStream* stream = inputFormatContext->streams[streamIndex];
  67.  
  68. AVCodecParameters* codecParameters = stream->codecpar;
  69.  
  70. if (!codecParameters->codec_id) {
  71. error = AVERROR_UNKNOWN;
  72. return 1;
  73. }
  74.  
  75.  
  76.  
  77. //Opening input
  78. decoderCodec = avcodec_find_decoder(codecParameters->codec_id);
  79.  
  80. decoderContext = avcodec_alloc_context3(decoderCodec);
  81. if (!decoderContext) {
  82. error = AVERROR_UNKNOWN;
  83. return 1;
  84. }
  85.  
  86. error = avcodec_parameters_to_context(decoderContext, codecParameters);
  87.  
  88. if(error){
  89. return 1;
  90. }
  91.  
  92. decoderContext->thread_count = 0;
  93. error = avcodec_open2(decoderContext, decoderCodec, nullptr);
  94.  
  95. if(error){
  96. return 1;
  97. }
  98. //Opened input
  99.  
  100.  
  101. //init frames
  102.  
  103. inputFrame = av_frame_alloc();
  104.  
  105. if(!inputFrame){
  106. error = AVERROR_UNKNOWN;
  107. return 1;
  108. }
  109.  
  110. outputFrame = av_frame_alloc();
  111.  
  112. if(!outputFrame){
  113. error = AVERROR_UNKNOWN;
  114. return 1;
  115. }
  116.  
  117.  
  118. decodePacket = av_packet_alloc();
  119.  
  120. if(!decodePacket){
  121. error = AVERROR_UNKNOWN;
  122. return 1;
  123. }
  124.  
  125. encodePacket = av_packet_alloc();
  126.  
  127. if(!encodePacket){
  128. error = AVERROR_UNKNOWN;
  129. return 1;
  130. }
  131.  
  132. //TODO
  133.  
  134. //open file
  135. dst_file = fopen(outputFile, "wb");
  136.  
  137. if (!dst_file) {
  138. fprintf(stderr, "Could not open destination file %s\n", outputFile);
  139. return 1;
  140. }
  141.  
  142. avformat_alloc_output_context2(&outputFormatContext, NULL, NULL, outputFile);
  143.  
  144. outputFormatContext->video_codec_id = av_guess_codec(outputFormatContext->oformat, NULL, outputFile, NULL, AVMEDIA_TYPE_VIDEO);
  145.  
  146. outputFormatContext->video_codec = avcodec_find_encoder(outputFormatContext->video_codec_id);
  147.  
  148. if(!outputFormatContext->video_codec){
  149. error = AVERROR_UNKNOWN;
  150. return 1;
  151. }
  152.  
  153. encoderContext = avcodec_alloc_context3(outputFormatContext->video_codec);
  154.  
  155. if(!encoderContext){
  156. error = AVERROR_UNKNOWN;
  157. return 1;
  158. }
  159.  
  160. encoderContext->width = 100;
  161. encoderContext->height = 100;
  162.  
  163.  
  164. encoderContext->pix_fmt = avcodec_find_best_pix_fmt_of_list(outputFormatContext->video_codec->pix_fmts, decoderContext->pix_fmt, true, NULL);
  165.  
  166. encoderContext->time_base = av_make_q(1, (stream->avg_frame_rate.num + (stream->avg_frame_rate.den / 2)) / stream->avg_frame_rate.den);
  167.  
  168. error = avcodec_open2(encoderContext, outputFormatContext->video_codec, nullptr);
  169.  
  170. if(error){
  171. return 1;
  172. }
  173. //init encoder
  174.  
  175. swsCtx = sws_getContext(decoderContext->width, decoderContext->height, decoderContext->pix_fmt,
  176. encoderContext->width, encoderContext->height, encoderContext->pix_fmt,
  177. 0, nullptr, nullptr, nullptr);
  178.  
  179.  
  180. if(!swsCtx){
  181. error = AVERROR_UNKNOWN;
  182. return 1;
  183. }
  184.  
  185. outputFrame->format = encoderContext->pix_fmt;
  186. outputFrame->width = encoderContext->width;
  187. outputFrame->height = encoderContext->height;
  188.  
  189.  
  190.  
  191.  
  192.  
  193. if (av_image_alloc(outputFrame->data, outputFrame->linesize, encoderContext->width, encoderContext->height, encoderContext->pix_fmt, 4) < 0) {
  194. puts("failed to allocate buffer");
  195. return 1;
  196. }
  197.  
  198. AVDictionary *opts = NULL;
  199.  
  200. error = av_dict_set(&opts, "loop", "0", 0);
  201. if(error){
  202.  
  203. switch(error){
  204.  
  205. case AVERROR_OPTION_NOT_FOUND:{
  206. puts("not found");
  207. break;
  208. }
  209.  
  210. case AVERROR(EINVAL):{
  211. puts("invalid");
  212. break;
  213. }
  214. case AVERROR(ERANGE):{
  215. puts("range");
  216. break;
  217. }
  218.  
  219.  
  220.  
  221. default:
  222. puts("unknown");
  223.  
  224. }
  225.  
  226. puts("failed to set option");
  227. // return 1;
  228. }
  229.  
  230.  
  231. AVStream* outstream = avformat_new_stream(outputFormatContext, NULL);
  232.  
  233. error = avcodec_parameters_from_context (outstream->codecpar, encoderContext) ;
  234.  
  235. if(error){
  236. puts("failed to get parameters from context");
  237. return 1;
  238. }
  239.  
  240. error = avformat_write_header(outputFormatContext, &opts);
  241.  
  242. if(error){
  243. puts("failed to write header");
  244. return 1;
  245. }
  246.  
  247. while (true) {
  248.  
  249. av_frame_unref(inputFrame);
  250. av_packet_unref(decodePacket);
  251.  
  252. //probably ended frames
  253. if(av_read_frame(inputFormatContext, decodePacket) < 0){
  254. puts("failed to read frames, ending");
  255. error = 0;
  256. break;
  257. }
  258.  
  259. //different stream. ignore.
  260. if (decodePacket->stream_index != streamIndex) {
  261. continue;
  262. }
  263.  
  264. //send packet
  265. error = avcodec_send_packet(decoderContext, decodePacket);
  266.  
  267. if (error < 0 ) {
  268.  
  269. //get next one
  270. if (error == AVERROR(EAGAIN)){
  271. continue;
  272. } else {
  273. return 1;
  274. }
  275. }
  276.  
  277. //send frame
  278. error = avcodec_receive_frame(decoderContext, inputFrame);
  279.  
  280. if (error < 0) {
  281.  
  282. //get next one
  283. if (error == AVERROR(EAGAIN)){
  284. continue;
  285. } else {
  286. return 1;
  287. }
  288. }
  289.  
  290. //we need to get the data
  291.  
  292. if(!sws_scale(swsCtx, inputFrame->data,
  293. inputFrame->linesize, 0, inputFrame->height, outputFrame->data, outputFrame->linesize)){
  294. return 1;
  295. }
  296.  
  297. //fwrite(dst_data[0], 1, dst_bufsize, dst_file);
  298.  
  299. error = avcodec_send_frame(encoderContext, outputFrame);
  300.  
  301. if(error){
  302. return 1;
  303. }
  304.  
  305. error = avcodec_receive_packet(encoderContext, encodePacket);
  306.  
  307. if(error){
  308. return 1;
  309. }
  310.  
  311. fwrite(encodePacket->data, 1, encodePacket->size, dst_file);
  312.  
  313.  
  314. }
  315.  
  316. // instead of directly sending the decoded frame to the encoder, we do a sws scale to convert the frame's pixel format and color range
  317. // prepare a buffer for the output frame to hold the scaled image data
  318. fclose(dst_file);
  319.  
  320.  
  321. av_packet_unref(decodePacket);
  322.  
  323. // flush the codec contexts with null packet
  324.  
  325. avcodec_send_packet(decoderContext, nullptr);
  326. av_packet_free(&decodePacket);
  327. av_frame_free(&inputFrame);
  328.  
  329. sws_freeContext(swsCtx);
  330.  
  331.  
  332. av_packet_free(&decodePacket);
  333.  
  334.  
  335. av_frame_free(&outputFrame);
  336.  
  337. avcodec_free_context(&encoderContext);
  338. avcodec_free_context(&decoderContext);
  339. avformat_close_input(&inputFormatContext);
  340. avformat_free_context(outputFormatContext);
  341.  
  342. av_free(outputFrameBuffer);
  343.  
  344. //transcode
  345.  
  346. return 0;
  347. }
  348.  
Advertisement
Add Comment
Please, Sign In to add comment