Advertisement
Guest User

Untitled

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