Advertisement
Guest User

Untitled

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